zoukankan      html  css  js  c++  java
  • 对制造者线程和使用者线程进行同步

    初始化如下:

    AutoResetEvent autoRestEvent = new AutoResetEvent(false);

    等待线程如下:

    1 Task.Factory.StartNew(()=> {
    2          if (autoRestEvent.WaitOne() == true)
    3          {
    4                Console.WriteLine("I got the signal");
    5          }
    6 });

    触发事件的线程如下:

    autoRestEvent.Set();

    1. 触发事件的线程autoRestEvent.Set()发出信号;

    2. 等待线程autoRestEvent.WaitOne()得到信号,并立刻将事件重置为无信号状态,开始往后执行。

    3. 可以像1,2步一样继续使用Set, WaitOne进行同步。

    AutoResetEvent与ManualResetEvent区别就是,manualResetEvent.WaitOne得到信号后,会一直处于有信号状态,不会自动重置事件为无信号状态,不能自动的反复使用set,waitOne,除非手动做reset。

    下面的示例演示使用 lock 关键字以及 AutoResetEventManualResetEvent 类对主线程和两个辅助线程进行线程同步。有关更多信息,请参见 lock 语句(C# 参考)

    该示例创建两个辅助线程。一个线程生成元素并将它们存储在非线程安全的泛型队列中。有关更多信息,请参见 Queue<T>。另一个线程使用此队列中的项。另外,主线程定期显示队列的内容,以便该队列可由三个线程进行访问。lock 关键字用于同步对队列的访问,以确保队列的状态不会被破坏。

    除了只是使用 lock 关键字来防止同时访问以外,还可以用两个事件对象提供进一步的同步。一个事件对象用来通知辅助线程终止,另一个事件对象由制造者线程用来在有新项添加到队列中时通知使用者线程。这两个事件对象封装在一个名为 SyncEvents 的类中。这使事件可以轻松传递给表示制造者线程和使用者线程的对象。SyncEvents 类按如下方式定义:

      1 using System;
      2 using System.Threading;
      3 using System.Collections;
      4 using System.Collections.Generic;
      5 
      6 public class SyncEvents
      7 {
      8     public SyncEvents()
      9     {
     10         _newItemEvent = new AutoResetEvent(false);
     11         _exitThreadEvent = new ManualResetEvent(false);
     12         _eventArray = new WaitHandle[2];
     13         _eventArray[0] = _newItemEvent;
     14         _eventArray[1] = _exitThreadEvent;
     15     }
     16 
     17     public EventWaitHandle ExitThreadEvent
     18     {
     19         get { return _exitThreadEvent; }
     20     }
     21     public EventWaitHandle NewItemEvent
     22     {
     23         get { return _newItemEvent; }
     24     }
     25     public WaitHandle[] EventArray
     26     {
     27         get { return _eventArray; }
     28     }
     29 
     30     private EventWaitHandle _newItemEvent;
     31     private EventWaitHandle _exitThreadEvent;
     32     private WaitHandle[] _eventArray;
     33 }
     34 public class Producer 
     35 {
     36     public Producer(Queue<int> q, SyncEvents e)
     37     {
     38         _queue = q;
     39         _syncEvents = e;
     40     }
     41     // Producer.ThreadRun
     42     public void ThreadRun()
     43     {
     44         int count = 0;
     45         Random r = new Random();
     46         while (!_syncEvents.ExitThreadEvent.WaitOne(0, false))
     47         {
     48             lock (((ICollection)_queue).SyncRoot)
     49             {
     50                 while (_queue.Count < 20)
     51                 {
     52                     _queue.Enqueue(r.Next(0,100));
     53                     _syncEvents.NewItemEvent.Set();
     54                     count++;
     55                 }
     56             }
     57         }
     58         Console.WriteLine("Producer thread: produced {0} items", count);
     59     }
     60     private Queue<int> _queue;
     61     private SyncEvents _syncEvents;
     62 }
     63 
     64 public class Consumer
     65 {
     66     public Consumer(Queue<int> q, SyncEvents e)
     67     {
     68         _queue = q;
     69         _syncEvents = e;
     70     }
     71     // Consumer.ThreadRun
     72     public void ThreadRun()
     73     {
     74         int count = 0;
     75         while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1)
     76         {
     77             lock (((ICollection)_queue).SyncRoot)
     78             {
     79                 int item = _queue.Dequeue();
     80             }
     81             count++;
     82         } 
     83         Console.WriteLine("Consumer Thread: consumed {0} items", count);
     84     }
     85     private Queue<int> _queue;
     86     private SyncEvents _syncEvents;
     87 }
     88 
     89 public class ThreadSyncSample
     90 {
     91     private static void ShowQueueContents(Queue<int> q)
     92     {
     93         lock (((ICollection)q).SyncRoot)
     94         {
     95             foreach (int item in q)
     96             {
     97                 Console.Write("{0} ", item);
     98             }
     99         }
    100         Console.WriteLine();
    101     }
    102 
    103     static void Main()
    104     {
    105         Queue<int> queue = new Queue<int>();
    106         SyncEvents syncEvents = new SyncEvents();
    107 
    108         Console.WriteLine("Configuring worker threads...");
    109         Producer producer = new Producer(queue, syncEvents);
    110         Consumer consumer = new Consumer(queue, syncEvents);
    111         Thread producerThread = new Thread(producer.ThreadRun);
    112         Thread consumerThread = new Thread(consumer.ThreadRun);
    113 
    114         Console.WriteLine("Launching producer and consumer threads...");        
    115         producerThread.Start();
    116         consumerThread.Start();
    117 
    118         for (int i=0; i<4; i++)
    119         {
    120             Thread.Sleep(2500);
    121             ShowQueueContents(queue);
    122         }
    123 
    124         Console.WriteLine("Signaling threads to terminate...");
    125         syncEvents.ExitThreadEvent.Set();
    126 
    127         producerThread.Join();
    128         consumerThread.Join();
    129     }
    130 
    131 }

    参考:http://msdn.microsoft.com/zh-cn/library/yy12yx1f(v=VS.90).aspx


     

  • 相关阅读:
    promiseall 使用一个ajax就可以调全部数据
    PHP中include和require的区别详解和使用建议
    phpredis中的connect和pconnect的区别
    <a>标签中的href="javascript:;"是什么意思?
    PHP中关于时间,时间戳 时区的设置问题
    javascript 超狠恶毒的禁用 右键 按键 禁用开发者工具 方法
    安装NoSQL数据库类型的redis 和 memcache数据库及其扩展
    XMind思维导图软件
    PHP代码中解决出现中文乱码的问题
    (七)mybatis-plus之generator(ftl模板生成:lombok swagger2 controloer的crud)
  • 原文地址:https://www.cnblogs.com/dirichlet/p/2158908.html
Copyright © 2011-2022 走看看