一、进程内部的线程同步
1、使用lock,用法如下:
private static readonly object SeqLock = new object(); private void Print() { lock (SeqLock) { Console.WriteLine("test"); } }
特性:只能传递对象,无法设置等待超时
2、使用:InterLocked(原子操作)
其在System.Threading命名空间下,Interlocked实际是类控制计数器,从而实现进程的同步,其很容易实现生产者消费者模型
//缓冲区,只能容纳一个字符 private static char buffer; //标识量(缓冲区中已使用的空间,初始值为0) private static long numberOfUsedSpace = 0; static void Main(string[] args) { //线程:写入者 Thread Writer = new Thread(delegate () { string str = "这里面的字会一个一个读取出来,一个都不会少,,,"; for (int i = 0; i < 24; i++) { //写入数据前检查缓冲区是否已满 //如果已满,就进行等待,直到缓冲区中的数据被进程Reader读取为止 while (Interlocked.Read(ref numberOfUsedSpace) == 1) { Thread.Sleep(50); } buffer = str[i]; //向缓冲区写入数据 //写入数据后把缓冲区标记为满(由0变为1) Interlocked.Increment(ref numberOfUsedSpace); } }); //线程:读出者 Thread Reader = new Thread(delegate () { for (int i = 0; i < 24; i++) { //读取数据前检查缓冲区是否为空 //如果为空,就进行等待,直到进程Writer向缓冲区中写入数据为止 while (Interlocked.Read(ref numberOfUsedSpace) == 0) { Thread.Sleep(50); } char ch = buffer; //从缓冲区读取数据 Console.Write(ch); Interlocked.Decrement(ref numberOfUsedSpace); } }); //启动线程 Writer.Start(); Reader.Start(); Console.ReadKey();
3、使用Monitor
其中Monitor.Enter()和lock相同
Monitor.Enter(obj){ //Synchronized part }finally{ Monitor.Exit(obj); }
TryEnter则可设置等待时间等
bool lockTaken=false; Monitor.TryEnter(obj, 500, ref lockTaken); if(lockTaken){ try { //Synchronized part } finally { Monitor.Exit(obj); } }else{ //don't aquire the lock, excute other parts }
二、进程间的同步
1. WaitHandle:
封装等待对共享资源进行独占访问的操作系统特定的对象。 WaitHandle:是一个抽象类,我们一般不直接用,而是用它的派生类:
AutoResetEvent、EventWaitHandle、ManualResetEvent、Mutex、Semaphore
这个抽象类的方法如下:
WaitOne(): 等待一个信号的出现,可设置超时;
WaitAll(): 等待多个信号的出现,可设置超时;
WaitAny(): 等待任意一个信号的出现,可设置超时;
2、Mutex:本文来源gao($daima.com搞@代@#码$网 与Monitor 类似,只有一个线程能够获取锁定。利用WaitOne() 获取锁定,利用ReleaseMutex() 解除锁定。构造函数使用如下:
bool isNew = false; mutex = new Mutex(false, "Mutex1", out isNew);
参数1:锁创建后是否由主调线程拥有。 如果设为true,相当于调用了WaitOne(),需要释放,否则其他线程无法获取锁;