锁定while循环条件不起作用

时间:2017-06-27 17:48:46

标签: c#

两个线程访问不同类中的相同静态变量。

        public void decrementCounter()
    {
        while (CounterClass.Counter > 0)
        {
            lock (this)
            {
                Thread.Sleep(1000);
                counterClass.RemoveValuesFromCounter(decrementRate);
                ItemsRemovedFromCounter += decrementRate;
                if(CounterClass.Counter<= decrementRate)
                {
                    decrementRate = CounterClass.Counter;
                }
                Console.WriteLine($" Items Removed by  Counter {ProcessCounterID} : {ItemsRemovedFromCounter}");
            }
        }
    }

public class CounterClass
{
    public static int Counter { get; private set; }
    public CounterClass(int counter)
    {
        Counter = counter;
    }

    public void RemoveValuesFromCounter(int val)
    {
        Counter -= val;
    }
}

当我创建n个线程时,每个线程运行decrementCounter()方法并在计数器类中递减计数器的值,直到它为零。我设置了一个锁以避免同时访问同一个线程,但它无法正常工作。

1 个答案:

答案 0 :(得分:1)

首先,如果每个线程都有一个包含decrementCounter的类的单独实例,那么你的锁绝对没有任何意义,因为每个线程都有自己独立的锁。您需要在所有线程之间共享一个锁定对象(它应该是一个锁定对象,没有其他任何东西可以访问,因此没有其他任何东西可能意外或故意获取锁定。)

但是假设你修复了这个并且锁在所有线程之间共享你还有另外一个问题:

您的锁只会阻止多个线程同时递减计数器。它不会阻止它们同时将其值作为while循环条件进行检查。

以下是可能发生的事情:

线程1访问CounterClass.Counter。假设它看到值1。因此它进入while循环体并进入锁定部分并进入休眠状态(Thread.Sleep)。

线程2访问CounterClass.Counter。它看到值1,因为尚未发生任何变化。它进入while循环体,然后在锁定处等待线程1离开。

线程1唤醒,递减计数器(并执行其他所有工作)。假设计数器现在为0.线程1离开lock部分。

线程2现在可以进入lock部分了。它递减计数器(并完成所有其他工作)。柜台现在是-1。线程2离开lock部分。

您需要在锁内移动CounterClass.Counter属性的访问权限。

但是这会破坏使用单独线程的整个目的,因为只有一个线程在给定时间实际执行任何操作,而所有剩余线程都在等待进入该关键部分。

如果不了解您正在尝试做的事情,就不可能说出如何修复它。