Mysterious Negative Counter Value

故事扮演 提交于 2019-12-02 18:30:10

问题


I'm creating new threads for every sql call for a project. There are millions of sql calls so I'm calling a procedure in a new thread to handle the sql calls.

In doing so, I wanted to increment and decrement a counter so that I know when these threads have completed the sql query.

To my amazement the output shows NEGATIVE values in the counter. HOW? When I am starting with 0 and adding 1 at the beginning of the process and subtracting 1 at the end of the process?

This int is not called anywhere else in the program.. the following is the code..

public static int counter=0;

while(!txtstream.EndOfStream)
{
    new Thread(delegate()
    {
        processline();
    }).Start();
    Console.WriteLine(counter);
}

public static void processline()
{
    counter++;
    sql.ExecuteNonQuery();
    counter--;
}

Output looks something like this:

1
21
-2
-2
5

回答1:


Nothing mysterious about it, you are using threading, right?

The ++ and -- operator aren't thread safe. Do this.

public static void processline()
{
    Interlocked.Increment(ref counter);
    sql.ExecuteNonQuery();
    Interlocked.Decrement(ref counter);
}



回答2:


How to overcome

Use Interlocked.Increment and Interlocked.Decrement to safely change the value of the counter.

Why this happens

You have counter as variable, which is shared across multiple threads. This variable is non-volatile and not wrapped by any synchronization block, so each thread has its own copy of that variable. So if two threads try to change it value at the same time, value would be overrriden by copy from thread which accessed it last.
Imagine you start your code in two different threads:
  1. Initially counter equals zero, both threads havy copy of that
  2. Both thread invoke increment their cached copies, and than change counter. So thread1 increments its copy to 1 and overrides counter, thread2 also increments its copy (still equal to zero) to 1 and overrides counter to, again, 1. After that that value is propagated to all threads (all copies are refreshed)
  3. Both threads invoke sql query. Due to variability in sql performance, these queries are completed in different time.
  4. Thread1 ends sql query, decrements counter from 1 to 0. Counter value is propagated to all threads
  5. After some time, Thread2 ends sql query, decrement counter from already propagated 0 to -1. Counter value is propagated to all threads. And it is -1.


来源:https://stackoverflow.com/questions/27322145/mysterious-negative-counter-value

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!