.NET 线程学习笔记二
来源:互联网 发布:淘宝自动秒杀软件 编辑:程序博客网 时间:2024/04/27 23:50
互斥锁:
//互斥锁是一个互斥的同步对象,这意味着在同一个时间有且仅有一个线程可以获取它。互斥锁适用于下列情况:
//一个共享资源每次只能被一个线程使用。例如:考虑一个由多个进程共享的日志文件,任意时刻只能有一个进程对//该文件执行写入操作。互斥锁是解决此类问题的最佳同步工具。
//互斥锁由System.Threading.Mutex类支持。该类有多个构造函数,其中最常用的两个是:
//publi Mutex()
//publi Mutex(bool owned)
//第一个版本创建一个处于未获取状态的互斥锁。
//在第二个版本中,如果owned为true,互斥锁的初始状态就是被主调线程所获取,否则处于未获取状态。
//要获取一个互斥锁,应当调用互斥锁上的WaitOne()方法。该方法继承于System.Threading.WaitHandle
//下面是它的最简单形式:
//public bool WaitOne();
//它将处于等待状态知道所调用的互斥锁可以被获取。因此该方法将阻塞主线程直到指定的互斥锁可用。该方法总是返回true.
//如果代码不再需要拥有互斥锁,可以调用下面的ReleaseMutex()方法来释放它:
//public void ReleaseMutex();
//在互斥锁上调用该方法将使得互斥锁被释放,从而允许该互斥锁被另一个线程所获取。
//要使用互斥锁来同步对共享资源的访问,需要使用WaitOne()和ReleaseMutex如下面的代码所示。
//Mutex myMtx = new Mutex();
//myMtx.WaitOne();
//myMtx.ReleaseMutex();
//在调用WaitOne()方法是,线程的执行将挂起直到获取互斥锁。在调用ReleaseMutex方法时,互斥锁将被释放,从而另一个线程可以获取它。
//通过这种方法,共享资源可以被限制为每次只允许一个线程访问。
public class ShardRes { public static int Count = 0; public static Mutex Mtx = new Mutex(); } class IncThread { int num; public Thread Thrd; public IncThread(string name, int n) { Thrd = new Thread(new ThreadStart(this.Run)); num = n; Thrd.Name = name; Thrd.Start(); } void Run() { Console.WriteLine(Thrd.Name + " is waiting for the mutex"); ShardRes.Mtx.WaitOne(); Console.WriteLine(Thrd.Name + " acquires the mutex."); do { Thread.Sleep(500); ShardRes.Count++; Console.WriteLine("In " + Thrd.Name + ",ShardRes.Count is" + ShardRes.Count); num--; } while (num > 0); Console.WriteLine(Thrd.Name + " releases the mutex."); ShardRes.Mtx.ReleaseMutex(); } } public class DecThread { int num; public Thread Thrd; public DecThread(string name, int n) { Thrd = new Thread(new ThreadStart(this.Run)); num = n; Thrd.Name = name; Thrd.Start(); } public void Run() { Console.WriteLine(Thrd.Name + " is waiting for the mutex"); ShardRes.Mtx.WaitOne(); do { Thread.Sleep(500); ShardRes.Count--; Console.WriteLine("In " + Thrd.Name + ",SharedRes.count is " + ShardRes.Count); num--; } while (num > 0); Console.WriteLine(Thrd.Name + " releases the mutex."); ShardRes.Mtx.ReleaseMutex(); } } class ThreadFive { public static void Main(string[] arg) { Console.WriteLine("ok"); IncThread mt1 = new IncThread("Increment Thread", 5); Thread.Sleep(1); DecThread mt2 = new DecThread("Decrement Thread", 5); mt1.Thrd.Join(); mt2.Thrd.Join(); Console.Read(); } }
信号量:
//信号量类似于互斥锁,但它可以允许多个线程同时访问一个共享资源。因此在同步一个资源集合的时候,信号量就显得非常有用。
//信号量通过一个计数器来控制对共享资源的访问。如果计数器大于0,那么就iu允许访问。如果计数器等于0,就拒绝访问。计数
//器累计的是“许可证”的个数。因此,为了访问某个资源,线程将阻塞直到得到一个许可证。
//信号量特别使用于下列情况:一个由“组(group)”或者"池(pool)"构成的共享资源。例如一个网络连接的集合,其中每一个连接
//都可以用于通信,这就是一个资源池。需要网络连接的线程并不关心它获取的是哪一个网络连接。在这种情况下,信号量提供了
//一种方便的机制来管理对连接的访问。
//信号量是由System.Threading.Semaphore实现的。它有多个构造函数,最简单形式为:
//public Semaphore(int initial,int max)
//其中,initial指定了信号量许可证计数器的初始值,它指定可用的许可证数目。计数器的最大值在max中传递。max地表了信号量
//最多拥有的许可证数目.initial的值指定了初始情况下有多少个许可证可用。
//获取信号量使用 WaitOne()
//不再需要使用信号量使用Release()方法释放。
//注意:
//线程在调用Release()之前可以多次调用WaitOne().但是,在释放许可证之前,WaitOne()的调用次数必须和Release()的调用次数一致。
//或者,也可以调用Release(int)形式,传入WaitOne()的调用次数。
class ThreadSix { public Thread Thr; static Semaphore sem = new Semaphore(2, 2); public ThreadSix(string name) { Thr = new Thread(this.Run); Thr.Name = name; Thr.Start(); } public void Run() { Console.WriteLine(Thr.Name + " is waiting for permit"); sem.WaitOne(); Console.WriteLine(Thr.Name + " is acquires for permit"); for (char ch = 'A'; ch < 'D'; ch++) { Console.WriteLine(Thr.Name + " : " + ch + " "); Thread.Sleep(500); } Console.WriteLine(Thr.Name + " releases a permit."); sem.Release(); } } public class SemaphoreDemo { static void Main(string[] arg) { ThreadSix t1 = new ThreadSix("one"); ThreadSix t2 = new ThreadSix("two"); ThreadSix t3 = new ThreadSix("three"); t1.Thr.Join(); t2.Thr.Join(); t3.Thr.Join(); Console.Read(); } }
//使用事件实现同步。
//同步事件有两种类型:ManualResetEvent(手工重置) AutoResetEvent(自动重置)
//事件处理非常简单。对于ManualResetEvent,其处理过程处理如下:等待某个事件
//的线程简单的代表该事件的事件对象上调用WaitOne();如果事件对象处于已发出
//信号状态,WaitOne将立即返回。它将挂起主调线程直到事件发出信号。在另一个线程执行事件之后,该线程通过调用
//Set()来把事件对象置于已发出信号状态,对WaitOne()的调用将返回,并且第一个线程恢复执行。
//调用Reset()将该事件重置为未发出信号状态。
public class ThreadSeven { public Thread Thrd; ManualResetEvent mre; public ThreadSeven(string name, ManualResetEvent evt) { Thrd = new Thread(this.Run); Thrd.Name = name; mre = evt; Thrd.Start(); } public void Run() { Console.WriteLine("Inside thread " + Thrd.Name); for (int i = 0; i < 5; i++) { Console.WriteLine(Thrd.Name); Thread.Sleep(500); } Console.WriteLine(Thrd.Name + " Done!"); mre.Set(); } } class ManualEventDemo { static void Main() { ManualResetEvent mre = new ManualResetEvent(false); ThreadSeven mt1 = new ThreadSeven("Event Thread 1", mre); Console.WriteLine("Main thread is waiting first event."); mre.WaitOne(); Console.WriteLine("Main thread received first event."); mre.Reset(); mt1 = new ThreadSeven("Event Thread 2", mre); mre.WaitOne(); Console.WriteLine("Main Thread received second event."); Console.Read(); } }
- .NET 线程学习笔记二
- VB.net学习笔记(二十四)线程基础
- VB.net学习笔记(二十七)线程同步上
- VB.net学习笔记(二十八)线程同步下
- java线程学习笔记(二)
- .NET 线程学习笔记一
- .net学习笔记(二)
- VB.net学习笔记(二十六)线程的坎坷人生
- android学习笔记之多线程(二)
- [C#基础]线程学习笔记(二)
- Java7线程学习笔记(二)
- Java线程池学习笔记二
- OS学习笔记二: 进程线程模型
- java学习笔记(二)线程
- Java线程学习笔记(二) 线程的异常捕捉
- Java学习笔记之线程(二):线程的常用方法
- ADO.NET学习笔记(二)
- ASP.Net 3.5学习笔记(C#)二
- Ubuntu下使用mysql
- 14.1.3 基于任务的并行度(task-based parallelism)
- SSL原理
- 装饰Jbutton
- struts2中Convention中的basePackage与locators配置种种
- .NET 线程学习笔记二
- 在Eclipse中查看Android源码
- Troj/TsuCom-Fam
- IPhone 开发经验教训总结 -- 仅供参考
- SDCard存储和File存储 的总结
- Struts2 Preparable与ModelDriven
- 虚拟机装苹果系统全过程
- shell下取得字符串的md5值
- ldd3学习笔记:调试技术