一.不同级别(Level)上的同步:
1.object level 同步
对应的class必须从ContextBoundObject继承(同步上下文context,使所有的方法调用能被截获),并且在
class上运用SynchronizationAttribute 。
2.Method level 同步
System.Runtime.CompilerService空间包含的一些属性将影响CLR在运行期间的行为。特性MethodImplAttribute可以用于需要进行同步控制的方法上。
3.code segment level 同步
(1)Monitor类(主要是静态方法)
Monitor.Enter(obj)//获得加在对象obj上的锁
...
Monitor.Exit(obj)//释放锁
//上面两句之间的代码相当于lock(obj){...}
Monitor.TryEnter(obj)//该方法立即返回,如果返回值为false,则接下来不需要Monitor.Exit(obj)。
//以下几个方法用于线程间的交互 ==》 解决同步依赖
Monitor.Wait(obj)//等待脉冲消息。释放对象上的锁并阻塞当前线程,以后只有其它线程调用Pulse或PulseAll时才会给它再次获得锁的机会
Monitor.Pulse(obj)//发射脉冲消息( 只有得到锁后才能发射,而且发射不会自动释放锁)
Monitor.PulseAll(obj)
注意:
(1)Monitor 锁定对象,只能在Enter()和Exit()之间的代码块中调用Wait和Pulse
(2)不能在一个线程中获得锁,而在另一个线程中释放锁。这样会产生锁丢失。 获得锁和释放锁应该在同一个线程中完成。
(3)lock语句
lock(obj)
{
需要进行同步的代码
}
(4)ReaderWriterLock类
实现单写多读程序的锁。
AcquireReaderLock()//当没有写程序线程占用锁时,就可获得锁
AcquireWriterLock()//当没有任何读写程序线程占用锁时,才可获得锁
ReleaseReaderLock()
ReleaseWriterLock()
(5)ManualResetEvent
Set()方法将状态设置为有信号
Reset()将其设置为无信号
WaitOne()将阻塞到其有信号为止,若调用WaitOne的时刻就是有信号的,将不会阻塞
(6)AutoResetEvent
与ManualResetEvent的区别是,AutoResetEvent.WaitOne()会自动改变事件对象的状态,即AutoResetEvent.WaitOne()每执行一次,事件的状态就改变一次。有信号-->无信号;无信号-->有信号
说明:
(1)无论是Monitor还是lock、ReaderWriterLock都只对引用类型的对象有效,因为引用类型的对象有一个隐藏的sync#字段,该字段的作用就是作为加锁的标记。
(2)上述的各种设施中,只有Monitor 和ManualResetEvent/AutoResetEvent 能解决线程间的同步依赖问题,而其它的设施主要用于解决临界资源共享。
4.member level同步
(1)Interlocked类(主要是静态方法)
同步一个由许多线程共享的变量。
Decrement(ref int);//使变量减1
Increment(ref int);//使变量加1
//以上两个方法仅针对类int变量
Exchange(ref object, object);
(2)ThreadStaticAttribute
该特性用于修饰静态变量,被该特性修饰的静态变量在每个线程中都有自己的副本。
二.创建线程安全的对象
Hashtable h = Hashtable.Synchronized(new Hashtable()) ;
ArrayList等容器也提供类似操作。