开发者

Race Condition while Increasing Int from threads

开发者 https://www.devze.com 2023-03-19 00:24 出处:网络
I have a method which just increases an Integer Value (i++) public void Calculate() { for(int i=0;i<1500;i++)

I have a method which just increases an Integer Value (i++)

public void Calculate()
{
for(int i=0;i<1500;i++)
 y++;
}

Where Y is Int Class Variable .

Thread thr1 = new Thread(Calculate);
thr1.Start();   
Thread thr2 = new Thread(Calculate);
thr2.Start();
Thread thr3 = new Thread(Calculate);
thr3.Start();
Thread thr4 = new Thread(Calculate);
thr4.Start();

By starting 4 Threads with Calculate Delegate ,the Y Value should be 6000 ,if Y starts with Value 0 But not always it became 6000 ,Sometimes im getting 5993 or 6003 so there are cases where this value is not the one which Logically should be . So is there any solution to prevent from that ,i dont want to Block Y while a thread is increasing ,so is there a way to set Variable Value Parallel from Multiply Threads ?

EDIT : It is working with Interlock.Increment(); but it slows down the Algorithm ,so w开发者_StackOverflowhat is doing it correct and faster is :

int i = 0;
int j = 0;
for (i = 0; i < 1500; i++)
{
j++;
this.label1.Text = y.ToString();
}
lock(y)
{
    y += j;
}


This is a race condition. You need to use Interlocked.Increment to do this in a threadsafe manner.


What you are experiencing is not loss of precision, but a result of a thread-unsafe way to access a variable. Since this variable is shared between different threads, you need to make sure that the increment operation is atomic. Once a thread A reads a value of a field, you must ensure that no other thread can change it before thread A writes the incremented value back.

To block other threads from doing this, use the Interlocked.Increment(ref Int32) static method to increase the value of the field atomically.

In this particular example, same results could be achieved without locking if each of your threads had its own private field to increment (you could then just add them all together at the end). You can try posting your actual code to see it can be modified in some similar way.


You can create a new object y with an int value, so you can lock object y when a thread wants to increment it. This makes Calculate() threadsafe.

            public void Calculate()
        {                
            for(int i = 0; i < 1500; i++)
            {
                lock (y)
                {
                    y.value++;
                }
            }
        }

The lock keyword ensures that one thread does not enter a critical section of code while another thread is in the critical section. If another thread tries to enter a locked code, it will wait, block, until the object is released.

http://msdn.microsoft.com/en-us/library/c5kehkcz%28v=VS.100%29.aspx


I'm no threading expert, so am donning flameproof suit for this answer in anticipation of howls of protest from people who really grok threads... but wouldn't the volatile keyword do what the OP wants in this case?

From the docs:

The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号