多线程:该使用哪种锁对象
Lock关键字锁定的代码块中,这样两个线程不能处理在同一时间的同一代码块。当一个线程退出锁定块,其他线程可以进入锁定的代码块。 Monitor类提供了相同的功能,但您指定的开始和与Monitor.Enter和Monitor.Exit锁定代码块的结尾。对于这两种方式,您需要一个变量来锁定。一个常见的模式是锁定在一个类或typeof运算(类型)为静态数据实例数据的。
using System; using System.Threading; public class LockObject { private static int counter = 0; public static void MonitorIncrement() { Monitor.Enter(typeof(LockObject)); counter++; Monitor.Exit(typeof(LockObject)); } public static void LockIncrement() { lock (typeof(LockObject)) { counter++; } } }
本typeof运算(类型)也可引起在一个不相关的代码块之外的完全不同的同步块锁定对象的问题。
其结果将导致两种完全不同的同步块同步两个不同的数据集从而阻止对方。其实可以使用一个字符串作为一个锁变量,因为所有的字符串指的是同一个实例。这些问题都可以通过一个私有只读字段来锁定!
public class LockObject { private static int counter = 0; private readonly static object syn = new object(); public static void MonitorIncrement() { Monitor.Enter(syn); counter++; Monitor.Exit(syn); } public static void LockIncrement() { lock (syn) { counter++; } } }
锁定的对象是私有因此它不能在类外部使用的代码块作为锁定对象!只读属性防止变量改变。
该例子中的问题通过使用Interlocked.Increment得到解决