{
Thread thread = new Thread( new ThreadStart(Do)); thread.Name = \ Thread1 \ ;
Thread thread2 = new Thread( new ThreadStart(Do)); thread2.Name = \ Thread2 \ ; thread.Start(); thread2.Start(); thread.Join(); thread2.Join(); Console.Read(); }
static void Do() {
if ( ! Monitor.TryEnter(m_monitorObject)) {
Console.WriteLine( \ Can't visit Object \ + Thread.CurrentThread.Name); return ; } try {
Monitor.Enter(m_monitorObject);
Console.WriteLine( \ Enter Monitor \ + Thread.CurrentThread.Name);
Thread.Sleep( 5000 ); } finally {
Monitor.Exit(m_monitorObject); } }
当线程1获取了m_monitorObject对象独占权时,线程2尝试调用TryEnter(m_monitorObject),此时会由于无法获取独占权而返回false,输出信息如下:
另外,Monitor还提供了三个静态方法Monitor.Pulse(Object o),Monitor.PulseAll(Object o)和Monitor.Wait(Object o ) ,用来实现一种唤醒机制的同步。关于这三个方法的用法,可以参考MSDN,这里就不详述了。 五、Mutex
在使用上,Mutex与上述的Monitor比较接近,不过Mutex不具备Wait,Pulse,PulseAll的功能,因此,我们不能使用Mutex实现类似的唤醒的功能。不过Mutex有一个比较大的特点,Mutex是跨进程的,因此我们可以在同一台机器甚至远程的机器上的多个进程上使用同一个互斥体。尽管Mutex也可以实现进程内的线程同步,而且功能也更强大,但这种情况下,还是推荐使用Monitor,因为Mutex类是win32封装的,所以它所需要的互操作转换更耗资源。
六、ReaderWriterLock
在考虑资源访问的时候,惯性上我们会对资源实施lock机制,但是在某些情况下,我们仅仅需要读取资源的数据,而不是修改资源的数据,在这种情况下获取资源的独占权无疑会影响运行效率,因此.Net提供了一种机制,使用
ReaderWriterLock进行资源访问时,如果在某一时刻资源并没有获取写的独占权,那么可以获得多个读的访问权,单个写入的独占权,如果某一时刻已经获取了写入的独占权,那么其它读取的访问权必须进行等待,参考以下代码:
Code private static ReaderWriterLock m_readerWriterLock = new ReaderWriterLock(); private static int m_int = 0; [STAThread] static void Main(string[] args) {
Thread readThread = new Thread(new ThreadStart(Read)); readThread.Name = \;
Thread readThread2 = new Thread(new ThreadStart(Read)); readThread2.Name = \;
Thread writeThread = new Thread(new ThreadStart(Writer)); writeThread.Name = \; readThread.Start(); readThread2.Start(); writeThread.Start(); readThread.Join(); readThread2.Join(); writeThread.Join();
Console.ReadLine(); }
private static void Read() {
while (true) {
Console.WriteLine(\\ + Thread.CurrentThread.Name + \AcquireReaderLock\);
m_readerWriterLock.AcquireReaderLock(10000);
Console.WriteLine(String.Format(\{0} m_int : {1}\, Thread.CurrentThread.Name, m_int)); m_readerWriterLock.ReleaseReaderLock(); } }
private static void Writer() {
while (true)
{
Console.WriteLine(\\ + Thread.CurrentThread.Name + \AcquireWriterLock\);
m_readerWriterLock.AcquireWriterLock(1000); Interlocked.Increment(ref m_int); Thread.Sleep(5000);
m_readerWriterLock.ReleaseWriterLock();
Console.WriteLine(\\ + Thread.CurrentThread.Name + \ReleaseWriterLock\); } }
在程序中,我们启动两个线程获取m_int的读取访问权,使用一个线程获取m_int的写入独占权,执行代码后,输出如下:
可以看到,当WriterThread获取到写入独占权后,任何其它读取的线程都必须等待,直到WriterThread释放掉写入独占权后,才能获取到数据的访问权,应该注意的是,上述打印信息很明显显示出,可以多个线程同时获取数据的读取权,这从ReadThread1和ReadThread2的信息交互输出可以看出。 七、SynchronizationAttribute
当我们确定某个类的实例在同一时刻只能被一个线程访问时,我们可以直接将类标识成Synchronization的,这样,CLR会自动对这个类实施同步机制,实际上,这里面涉及到同步域的概念,当类按如下设计时,我们可以确保类的实例无法被多个线程同时访问

