转载地址http://blog.csdn.net/gulijiang2008/article/details/7257422

一. 为什么要lock,lock了什么?

当我们使用线程的时候,效率最高的方式当然是异步,即各个线程同时运行,其间不相互依赖和等待。但当不同的线程都需要访问某个资源的时候,就需要同步机制了,也就是说当对同一个资源进行读写的时候,我们要使该资源在同一时刻只能被一个线程操作,以确保每个操作都是有效即时的,也即保证其操作的原子性。lock是C#中最常用的同步方式,格式为lock(objectA){codeB} 。
lock(objectA){codeB} 看似简单,实际上有三个意思,这对于适当地使用它至关重要:
1. objectA被lock了吗?没有则由我来lock,否则一直等待,直至objectA被释放。
2. lock以后在执行codeB的期间其他线程不能调用codeB,也不能使用objectA。
3. 执行完codeB之后释放objectA,并且codeB可以被其他线程访问。

二. lock(this)怎么了?

我们看一个例子:
lock
using System;
using System.Threading;

namespace Namespace1
{
    class C1
     {
        privatebool deadlocked= true;

//这个方法用到了lock,我们希望lock的代码在同一时刻只能由一个线程访问
        publicvoid LockMe(object o)
         {
            lock (this)
             {
                while(deadlocked)
                 {
                     deadlocked = (bool)o;
                     Console.WriteLine("Foo: I am locked :(");
                     Thread.Sleep(500);
                 }
             }
         }

//所有线程都可以同时访问的方法
        publicvoid DoNotLockMe()
         {
             Console.WriteLine("I am not locked :)");
         }
     }

class Program
     {
        staticvoid Main(string[] args)
         {
             C1 c1 =new C1();

//在t1线程中调用LockMe,并将deadlock设为true(将出现死锁)
             Thread t1= new Thread(c1.LockMe);
             t1.Start(true);
             Thread.Sleep(100);

//在主线程中lock c1
            lock (c1)
             {
                //调用没有被lock的方法
                 c1.DoNotLockMe();
                //调用被lock的方法,并试图将deadlock解除
                 c1.LockMe(false);
             }
         }
     }

在t1线程中,LockMe调用了lock(this), 也就是Main函数中的c1,这时候在主线程中调用lock(c1)时,必须要等待t1中的lock块执行完毕之后才能访问c1,即所有c1相关的操作都无法完成,于是我们看到连c1.DoNotLockMe()都没有执行。
 
把C1的代码稍作改动:
C1
    class C1
     {
        privatebool deadlocked= true;
        privateobject locker= newobject();

//这个方法用到了lock,我们希望lock的代码在同一时刻只能由一个线程访问
        publicvoid LockMe(object o)
         {
            lock (locker)
             {
                while(deadlocked)
                 {
                     deadlocked = (bool)o;
                     Console.WriteLine("Foo: I am locked :(");
                     Thread.Sleep(500);
                 }
             }
         }

//所有线程都可以同时访问的方法
        publicvoid DoNotLockMe()
         {
             Console.WriteLine("I am not locked :)");
         }
     }

这次我们使用一个私有成员作为锁定变量(locker),在LockMe中仅仅锁定这个私有locker,而不是整个对象。这时候重新运行程序,可以看到虽然t1出现了死锁,DoNotLockMe()仍然可以由主线程访问;LockMe()依然不能访问,原因是其中锁定的locker还没有被t1释放。
 
关键点:
1. lock(this)的缺点就是在一个线程锁定某对象之后导致整个对象无法被其他线程访问。
2. 锁定的不仅仅是lock段里的代码,锁本身也是线程安全的。
3. 我们应该使用不影响其他操作的私有对象作为locker。
4. 在使用lock的时候,被lock的对象(locker)一定要是引用类型的,如果是值类型,将导致每次lock的时候都会将该对象装箱为一个新的引用对象(事实上如果使用值类型,C#编译器(3.5.30729.1)在编译时就会给出一个错误)。
kenny add

而对于Monitor,发现它的静态方法Enter(object obj)有一个异常类型ArgumentNullException,

执行lock(null对象 )处,抛出未处理的异常:System.ArgumentNullException: 值不能为空!

在代码段中修改锁定对象,会出现 blance<0的情况,并会抛出异常

private static readonly object obj = new object();

为什么要设置成只读的呢?这是因为如果在lock代码段中改变obj的值,其它线程就畅通无阻了,因为互斥锁的对象变了,object.ReferenceEquals必然返回false。

所以把上面的修改成private static readonly

转载于:https://www.cnblogs.com/juefeiye/archive/2013/05/01/lock_this_lock_object.html

转载 为什么不要 lock(this) ? lock object 并是readonly相关推荐

  1. mysql MDL锁如何解决_MYSQL METADATA LOCK(MDL LOCK)MDL锁问题分析

    一.前言 MYSQL中MDL锁一直是一个比较让人比较头疼的问题,我们谈起锁一般更加倾向于INNODB下层的gap lock.next key lock.row lock等,因为它很好理解,也很好观察, ...

  2. OpenWrt——Could not lock /var/lock/opkg.lock: Resource temporarily unavailable.

    问题描述 root@OpenWrt:~# opkg update Collected errors:* opkg_conf_load: Could not lock /var/lock/opkg.lo ...

  3. Mysql INNODB引擎行锁的3种算法 Record Lock Next-Key Lock Grap Lock

    Mysql INNODB引擎行锁的3种算法 InnoDB存储引擎有3种行锁的算法,其分别是: □ Record Lock:单个行记录上的锁 Record Lock总是会去锁住索引记录,如果InnoDB ...

  4. Dumping all threads without appropriate locks held: thread list lock mutator lock报错原因?

    以下报错是什么原因呢?跟了很久的代码,也没有找到具体原因 2021-07-16 16:30:15 07-16 16:30:15.825 11812 13216 I HwAudioRecordImpl: ...

  5. 关于Application.Lock和Lock(obj)

    1.Application.Lock和Application.UnLock一般配对出现,用于锁住Lock与UnLock之间的所有代码(注意不光锁住对于Application的赋值). 2.Lock(o ...

  6. FLUSH TABLES WITH READ LOCK 和 LOCK TABLES

    今天在解决数据库同步异常的时候用到了flush tables with read lock 这个命令,于是顺便就学习了下锁表的相关知识. 1.FLUSH TABLES WITH READ LOCK 这 ...

  7. FLUSH TABLES WITH READ LOCK 和 LOCK TABLES比较

    1.FLUSH TABLES WITH READ LOCK 这个命令是全局读锁定,执行了命令之后所有库所有表都被锁定只读.一般都是用在数据库联机备份,这个时候数据库的写操作将被阻塞,读操作顺利进行.解 ...

  8. Mysql 死锁过程及案例详解之插入意向锁与自增锁备份锁日志锁Insert Intention Lock Auto-increment Lock Backup Lock Log Lock

    Mysql 插入意向锁与自增锁备份锁日志锁 插入意向锁Insert Intention Lock 插入意向锁Insert intention locks是记录级别的,它通过"INSERT&q ...

  9. Mysql 死锁过程及案例详解之记录锁与间隔锁Record Lock Gap Lock

    记录锁Record Lock与间隔锁GAP Lock 记录锁Record Lock 记录锁Record Locks又称为行锁,它同时包含索引和间隔锁.记录锁可以是共享锁也可能是排他锁.可以通过perf ...

最新文章

  1. 使用httpClient发送get\post请求
  2. Silverlight2 边学边练 之三 小球自由落体
  3. Jmeter将JDBC Request查询结果作为下一个接口参数方法
  4. 无电池摄像头如何实现高清晰度视频编码?
  5. 【每日SQL打卡】​​​​​​​​​​​​​​​DAY 18丨即时食物配送 I【难度简单】​
  6. Postman接口压力测试
  7. html页面可以用在webview,使用WebView加载HTML代码
  8. 使用Scipy进行函数优化
  9. Lighttpd 启用 HTTPS 并重定向 HTTP 为 HTTPS 访问配置
  10. Task 4 用户输入->知识库的查询语句
  11. Qt多人协作项目执行方案
  12. 第一课 语言的发展史
  13. IRQL-NOT-LESS-OR-EQUAL异常分析
  14. 【转】大学四年因为知道了这32个网站,我成了别人眼中的大神!
  15. Java语言查询附近店铺算法
  16. python绘制并列的条形图的方法_python matplotlib库绘制条形图练习题
  17. 文件系统——空闲块成组链接法的模拟
  18. 克服反爬虫机制爬取智联招聘网站
  19. 使用EDI与SAP集成的解决方案
  20. 3dsMax模型转UE4

热门文章

  1. Python 之 Pandas (六)合并
  2. 最简单的t-SNE上手使用
  3. Hadmard product(哈达玛积)
  4. 从宇宙、互联网和脑的关系看元宇宙的终极形态
  5. 霍金 | 哥德尔和物理学的终结
  6. 中国工程院2021年院士增选第二轮候选人名单公布
  7. 时空大数据可视化表达分析,看MapGIS七大“超能力”
  8. 工业智联网: 基本概念、关键技术与核心应用
  9. 预测|十张图带你了解2018年机器人行业趋势与前景
  10. 波士顿动力新年视频第一发,机器人狗能为朋友开门了!