13

我想知道:锁定只允许 1 个线程进入代码区域

等待句柄用于发信号: :

信号是当一个线程等待,直到它收到来自另一个的通知。

所以我心想,这个可以用来代替锁吗?

就像是 :

Thread number 1 --please enter ( autoreset --> autlock)
dowork...
finish work...
set signal  to invite the next thread

所以我写了这个:

/*1*/   static EventWaitHandle _waitHandle = new AutoResetEvent(true);
/*2*/   
/*3*/   volatile int i = 0;
/*4*/   void Main()
/*5*/   {
/*6*/   
/*7*/       for (int k = 0; k < 10; k++)
/*8*/       {
/*9*/           var g = i;
/*10*/           Interlocked.Increment(ref i);
/*11*/           new Thread(() = > DoWork(g)).Start();
/*12*/   
/*13*/       }
/*14*/   
/*15*/       Console.ReadLine();
/*16*/   }
/*17*/   
/*18*/   
/*19*/   void DoWork(object o)
/*20*/   {
/*21*/       _waitHandle.WaitOne();
/*22*/       Thread.Sleep(10);
/*23*/       Console.WriteLine((int) o + "Working...");
/*24*/       _waitHandle.Set();
/*25*/   
/*26*/   }

如您所见:第 21 行、第 24 行是锁的替代品。

问题 :

  • 它是有效的替代品吗?(不是我会替换lock ,而是想知道使用场景)
  • 我应该什么时候使用每个?

谢谢你。

奇怪但SO不包含关于_lock vs EventWaitHandle_

4

2 回答 2

20

不要去那边。锁的一个重要特性是它提供了公平性。换句话说,一个合理的保证,竞争锁的线程得到了他们最终可以获得它的保证。Monitor 类提供了这样的保证,由 CLR 中的等待队列实现。而 Mutex 和 Semaphore 提供了这样的保证,由操作系统实现。

WaitHandles提供这样的保证。如果锁被争用,这是非常有害的,同一个线程可以重复获取它,而其他线程可能永远饿死。

为锁使用适当的同步对象。等待句柄应该只用于信号。

于 2013-06-24T11:24:57.007 回答
1

这是可能的,但它比 lock() 慢得多,而且更难维护。

顺便说一句,在使用 Interlocked-methods 维护它时,您永远不应该直接读取一个值。

您的代码应如下所示:

var g = Interlocked.Increment(ref i);

然后 g 将包含增加的值而不是任意的先前值。

于 2013-06-24T11:13:13.670 回答