Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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#_Multithreading - Fatal编程技术网

C# 生产者-消费者示例,都在锁(此)块中

C# 生产者-消费者示例,都在锁(此)块中,c#,multithreading,C#,Multithreading,我在这一页上看了示例2,关于Monitor.Pulse()的线程同步 创建单元对象并将其传递给生产者和使用者对象 Cell cell = new Cell( ); CellProd prod = new CellProd(cell, 20); CellCons cons = new CellCons(cell, 20); 将为这两个线程中的每一个创建一个线程 Thread producer = new Thread(new ThreadStart(prod.ThreadRun)); Threa

我在这一页上看了示例2,关于Monitor.Pulse()的线程同步

创建单元对象并将其传递给生产者和使用者对象

Cell cell = new Cell( );
CellProd prod = new CellProd(cell, 20);
CellCons cons = new CellCons(cell, 20);
将为这两个线程中的每一个创建一个线程

Thread producer = new Thread(new ThreadStart(prod.ThreadRun));
Thread consumer = new Thread(new ThreadStart(cons.ThreadRun));
每种情况下的ThreadRun都是一个调用Cell.ReadFromCell()或Cell.WriteToCell()的循环,具体取决于使用者/生产者。例如,制作人就是这样做的

public void ThreadRun( )
{
  for(int looper=1; looper<=quantity; looper++)
     cell.WriteToCell(looper);  // "producing"
}
由于传递给这两个对象的是同一个Cell对象(即上面lock语句中的“this”),我认为一次只能有一个线程在这段代码中。然而,从Monitor.Pulse()和Monitor.Wait()后面的代码来看,这两个线程似乎同时在这些部分中。如果一个线程拥有锁并点击了Monitor.Wait(),那么另一个线程就永远不会脉冲,因为它在等待锁时被阻塞了


我猜有一个简单的解决方案,我误解了一些东西,从我运行代码的测试来看,两个线程似乎同时处于其关键部分,所以锁(这)没有做我印象中应该做的事情。

您缺少的是
监视器。等等(这)
将释放此上的锁,直到它被唤醒。所以是的,你的消费者线程看起来像是在锁中,因此拥有它,但实际上它是暂时释放的

发件人:

当线程调用Wait时,它释放对象上的锁并进入对象的等待队列。对象就绪队列中的下一个线程(如果有)获取锁并独占使用对象。所有调用Wait的线程都将保持在等待队列中,直到它们接收到锁所有者发送的来自Pulse或pulsell的信号。如果发送脉冲,则仅影响等待队列头部的线程。如果发送PULSELL,则等待对象的所有线程都会受到影响。当接收到信号时,一个或多个线程离开等待队列并进入就绪队列。允许就绪队列中的线程重新获取锁


请注意,
锁定(此)
是一种糟糕的编程实践。相反,创建一个object类型的私有字段并锁定它。这是一个糟糕的做法的原因是,任何人都可以在那个物体上取下锁;如果您的锁顺序保证只依赖于类型内的代码能够锁定,那么锁定会使代码脆弱且难以分析。锁定私有对象意味着您知道只有能够获取私有对象引用的代码才能解除锁定。Eric,我完全同意,但MSDN首先不应该提供这样的示例代码。大多数情况下,人们使用“lock(this)”语句是因为他们认为如果它出现在MSDN上,那么它一定是正确的方式。有没有办法提交更新MSDN内容的请求?@SolutionYogi:很好。我会提请文档经理注意。谢谢@解决方案Yogi:文档经理向我指出,所讨论的页面来自2003年。更新的页面使用更好的方法声明私有对象:。不幸的是,许多时间错误仍然存在于较旧的页面上,因为花费大量时间搜索数百万页十年前的文档以查找错误是极其昂贵的。@EricLippert,我完全理解几乎不可能更新每个文档。这就是为什么我想知道是否有任何方法可以记录请求(比如我们如何使用Connect处理bug)以更新文档。谢谢你调查这件事。
lock(this)