Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 神秘的负计数器值_C#_Sql_Counter - Fatal编程技术网

C# 神秘的负计数器值

C# 神秘的负计数器值,c#,sql,counter,C#,Sql,Counter,我正在为项目的每个sql调用创建新线程。有数以百万计的sql调用,所以我在一个新线程中调用一个过程来处理sql调用 在这样做时,我想增加和减少一个计数器,以便知道这些线程何时完成了sql查询 令我惊讶的是,计数器的输出显示为负值。怎样?当我从0开始,在过程开始时加1,在过程结束时减1 程序中的其他任何地方都不会调用此int。。下面是代码 public static int counter=0; while(!txtstream.EndOfStream) { new Thread(del

我正在为项目的每个sql调用创建新线程。有数以百万计的sql调用,所以我在一个新线程中调用一个过程来处理sql调用

在这样做时,我想增加和减少一个计数器,以便知道这些线程何时完成了sql查询

令我惊讶的是,计数器的输出显示为负值。怎样?当我从0开始,在过程开始时加1,在过程结束时减1

程序中的其他任何地方都不会调用此int。。下面是代码

public static int counter=0;

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

public static void processline()
{
    counter++;
    sql.ExecuteNonQuery();
    counter--;
}
输出如下所示:

1
21
-2
-2
5

没有什么神秘的,你在使用线程,对吗

++
-->
运算符不是线程安全的。这样做

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

没有什么神秘的,你在使用线程,对吗

++
-->
运算符不是线程安全的。这样做

public static void processline()
{
    Interlocked.Increment(ref counter);
    sql.ExecuteNonQuery();
    Interlocked.Decrement(ref counter);
}
如何克服 使用
Interlocked.Increment
Interlocked.decreation
安全地更改计数器的值。 为什么会发生这种情况您将计数器作为变量,它在多个线程之间共享。这个变量是非易失性的,不被任何同步块包装,因此每个线程都有自己的该变量副本。所以,若两个线程试图同时更改它的值,那个么最后访问它的线程的副本将覆盖该值
想象您在两个不同的线程中启动代码:

  • 最初计数器等于零,两个线程都有该计数器的副本
  • 这两个线程都调用它们的缓存副本,然后更改计数器。因此,thread1将其副本增加到1并覆盖计数器,thread2也将其副本(仍然等于零)增加到1,并再次将其覆盖计数器增加到1。之后,该值将传播到所有线程(刷新所有副本)
  • 两个线程都调用sql查询。由于sql性能的可变性,这些查询在不同的时间完成
  • Thread1结束sql查询,将计数器从1递减到0。计数器值传播到所有线程
  • 一段时间后,Thread2结束sql查询,将计数器从已传播的0递减为-1。计数器值将传播到所有线程。它是-1
  • 如何克服 使用
    Interlocked.Increment
    Interlocked.decreation
    安全地更改计数器的值。 为什么会发生这种情况您将计数器作为变量,它在多个线程之间共享。这个变量是非易失性的,不被任何同步块包装,因此每个线程都有自己的该变量副本。所以,若两个线程试图同时更改它的值,那个么最后访问它的线程的副本将覆盖该值
    想象您在两个不同的线程中启动代码:

  • 最初计数器等于零,两个线程都有该计数器的副本
  • 这两个线程都调用它们的缓存副本,然后更改计数器。因此,thread1将其副本增加到1并覆盖计数器,thread2也将其副本(仍然等于零)增加到1,并再次将其覆盖计数器增加到1。之后,该值将传播到所有线程(刷新所有副本)
  • 两个线程都调用sql查询。由于sql性能的可变性,这些查询在不同的时间完成
  • Thread1结束sql查询,将计数器从1递减到0。计数器值传播到所有线程
  • 一段时间后,Thread2结束sql查询,将计数器从已传播的0递减为-1。计数器值将传播到所有线程。它是-1

  • 这是非常基本的线程。两个线程可以在写入同一个值之前读取该值,那么两个加法的结果将仅为一个加法。然后,两次减法得到的总值是-1Ah,我明白了。。。谢谢你的解释。这是非常基本的线程。两个线程可以在写入同一个值之前读取该值,那么两个加法的结果将仅为一个加法。然后,两次减法得到的总值是-1Ah,我明白了。。。谢谢你的解释。