锁的本质 是互斥量.
互斥量可以通俗的这么理解.(本质不同,但表像是相同的,这样描述更易理解,使用上也不容易出错)
以一个以对象(指针)的值(指向地址)作为Key的集合作为基础.
所有线程在进入锁的时刻,
判断如果Key存在,
线程挂起并进入等待队列.
否则
线程进入锁,并添加Key到集合.
线程执行结束,移除集合中的锁.
唤醒挂起的等待队列.
MSDN规范
通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。
常见写法
lock (this)、lock (typeof (MyType))、lock(“lockKey")、lock(obj)
1 lock(this)
代码效果:以this作为Key,那么此锁只对所有该实例存在线程生效.
常见问题:new了2个this,则锁中可同时存在2个线程. 可能超出预期.
2 lock(typeof(MyType))
代码效果:以type作为Key,此锁对整个可见MyType类型的程序集生效.
常见问题:因为MyType的可访问级别较高(public),可能会在类外面加锁,从而导致预期的线程无法进入,从而挂起.
而且对typeof(MyType)加锁的系统开销较大.可能会超出预期.
3 lock("lockKey")
代码效果:以字符串所在地址作为Key,此锁对整进程生效.(因为C# 进程中所有字符串统一管理..)
常见问题:任意代码位置的 lock("lockKey") 都会导致其他线程无法进入. 从而挂起. 这样可能会不符合设计人员的初衷.
4 lock(obj)
代码效果:以obj所指向内容作为key, 此锁仅对 对obj可见的代码 生效.
常见问题:如果obj为static,则锁是唯一锁,如果obj为成员变量,则锁为实例锁,等同于 lock(this).
结论:
要根据实际情况使用lock... 自己决定要锁起来的代码范围. 除了第二种写法有明显问题,,其他3种写法都是正常的..
只要搞清楚锁定的范围和线程让代码达到自己的预期就可以了.