Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.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# 如果我从Albahari的生产者/消费者队列实现中删除lock(),会发生什么_C#_.net_Multithreading - Fatal编程技术网

C# 如果我从Albahari的生产者/消费者队列实现中删除lock(),会发生什么

C# 如果我从Albahari的生产者/消费者队列实现中删除lock(),会发生什么,c#,.net,multithreading,C#,.net,Multithreading,我正在学习多线程,遇到了生产者/消费者的问题 以下是《简而言之》系列丛书的作者: 使用系统; 使用系统线程; 使用System.Collections.Generic; 类ProducerConsumerQueue:IDisposable { EventWaitHandle_wh=新的自动存储事件(false); 螺纹工; 只读对象_locker=新对象(); 队列_tasks=新队列(); 公共产品消费者队列() { _工人=新线程(工作); _worker.Start(); } 公共void

我正在学习多线程,遇到了生产者/消费者的问题

以下是《简而言之》系列丛书的作者:

使用系统;
使用系统线程;
使用System.Collections.Generic;
类ProducerConsumerQueue:IDisposable
{
EventWaitHandle_wh=新的自动存储事件(false);
螺纹工;
只读对象_locker=新对象();
队列_tasks=新队列();
公共产品消费者队列()
{
_工人=新线程(工作);
_worker.Start();
}
公共void排队任务(字符串任务)
{
锁(_locker)/
队列
不是线程安全的

如果您从多个线程写入,它将中断。
(可能是两个线程同时尝试调整缓冲区大小时)


此外,即使是线程安全的,移除第二个锁也会允许第二个线程移除最后一项,而第一个线程位于
if
中,使第一个线程尝试读取一个空队列。

在他的最后一句话中,SLaks指的是工作()方法。但是在单个对象实例上只能有一个线程执行该方法。那么,为什么我们需要第二个锁呢?@Junior1993:因为这些方法不是线程安全的,所以队列仍然可以中断。SLaks,请您详细解释一下(一步一步)如果我们只移除第二个锁,它怎么会断开?@Junior1993:一个线程调用
Enqueue()
,而另一个线程调用
Dequeue()
。在第一个线程将队列大小调整为新数组后,第二个线程修改了旧数组。我只是好奇我的问题有什么不对,有人否决了它?”
using System;
using System.Threading;
using System.Collections.Generic;

class ProducerConsumerQueue : IDisposable
{
  EventWaitHandle _wh = new AutoResetEvent (false);
  Thread _worker;
  readonly object _locker = new object();
  Queue<string> _tasks = new Queue<string>();

  public ProducerConsumerQueue()
  {
    _worker = new Thread (Work);
    _worker.Start();
  }

  public void EnqueueTask (string task)
  {
    lock (_locker) // <---------------------------------------------- 1
      _tasks.Enqueue (task);
    _wh.Set();
  }

  public void Dispose()
  {
    EnqueueTask (null);     // Signal the consumer to exit.
    _worker.Join();         // Wait for the consumer's thread to finish.
    _wh.Close();            // Release any OS resources.
  }

  void Work()
  {
    while (true)
    {
      string task = null;
      lock (_locker) // <---------------------------------------------- 2
        if (_tasks.Count > 0)
        {
          task = _tasks.Dequeue();
          if (task == null) return;
        }
      if (task != null)
      {
        Console.WriteLine ("Performing task: " + task);
        Thread.Sleep (1000);  // simulate work...
      }
      else
        _wh.WaitOne();         // No more tasks - wait for a signal
    }
  }
}