一. 为什么要用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)怎么了?

  我们看一个例子:

using System;
using System.Threading; namespace Namespace1
{
class C1
{
private bool deadlocked= true; //这个方法用到了lock,我们希望lock的代码在同一时刻只能由一个线程访问
public void LockMe(object o)
{
lock (this)
{
while(deadlocked)
{
deadlocked = (bool)o;
Console.WriteLine("Foo: I am locked :(");
Thread.Sleep();
}
}
} //所有线程都可以同时访问的方法
public void DoNotLockMe()
{
Console.WriteLine("I am not locked :)");
}
} class Program
{
static void Main(string[] args)
{
C1 c1 = new C1(); //在t1线程中调用LockMe,并将deadlock设为true(将出现死锁)
Thread t1= new Thread(c1.LockMe);
t1.Start(true);
Thread.Sleep(); //在主线程中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的代码稍作改动:

class C1
{
private bool deadlocked= true;
private object locker= new object(); //这个方法用到了lock,我们希望lock的代码在同一时刻只能由一个线程访问
publicvoid LockMe(object o)
{
lock (locker)
{
while(deadlocked)
{
deadlocked = (bool)o;
Console.WriteLine("Foo: I am locked :(");
Thread.Sleep();
}
}
} //所有线程都可以同时访问的方法
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)在编译时就会给出一个错误)。

  备注:

  对于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/chenheng0056/p/3444304.html

为什么要用lock 【readonly】object?为什么不要lock(this)?的更多相关文章

  1. [问题解决] initAndListen: 10309 Unable to create/open lock file: /data/db/mongod.lock

    错误: 在linux下开启mongoDB的 $ >bin: ./mongod 时报错:initAndListen: 10309 Unable to create/open lock file: ...

  2. E:Could not get lock /var/lib/apt/lists/lock - open (11: Resource temporarily unavailable)

    出现这个问题的原因可能是有另外一个程序正在运行,导致资源被锁不可用.而导致资源被锁的原因,可能是上次安装时没正常完成,而导致出现此状况. 解决方法:输入以下命令 sudo rm /var/cache/ ...

  3. Synchronized和Lock, 以及自旋锁 Spin Lock, Ticket Spin Lock, MCS Spin Lock, CLH Spin Lock

    Synchronized和Lock synchronized是一个关键字, Lock是一个接口, 对应有多种实现. 使用synchronized进行同步和使用Lock进行同步的区别 使用synchro ...

  4. 解决 E: Could not get lock /var/lib/apt/lists/lock

    参考:Unable to lock the administration directory (/var/lib/dpkg/) is another process using it? 在更换软件源时 ...

  5. Could not get lock /var/lib/apt/lists/lock

    执行: apt-get update 出现 Could not get lock /var/lib/apt/lists/lock 解决办法: 查询与apt相关的进程 ps -e | grep apt ...

  6. 解决Could not get lock /var/cache/apt/archives/lock

    在ubuntu apt-get upgrade的时候,遇到: E: Could not get lock /var/cache/ apt/archives/lock - open (11 Resour ...

  7. Ubuntu遇到apt-get update报错:"E: Could not get lock /var/lib/apt/lists/lock"

    sudo apt-get update报错:"E: Could not get lock /var/lib/apt/lists/lock" 出现此问题的原因可能是有另外一个程序在运 ...

  8. ubuntu E: Could not get lock /var/lib/apt/lists/lock 异常信息

    转载:https://www.cnblogs.com/qq952693358/p/6537846.html 在更换软件源时遇到了如下问题: sudo apt-get update E: Could n ...

  9. Could not open lock file/var/lib/dpkg/lock的解决

    Could not open lock file/var/lib/dpkg/lock的解决 在ubuntu系统中利用apt-get install something的时候,有时候会出现无法获得锁的权 ...

  10. sudo apt-get update:Could not get lock /var/lib/apt/lists/lock解决办法

    原文: http://blog.chinaunix.net/uid-26932153-id-3193335.html 今天更新时候出现了点小问题,一开始更新到一半,我嫌速度慢,就取消掉了. 更新了so ...

随机推荐

  1. [leetcode.com]算法题目 - Same Tree

    Given two binary trees, write a function to check if they are equal or not. Two binary trees are con ...

  2. Ubuntu修改apt-get源

    1.背景 服务器上安装了最新的Ubuntu Server 17.04,代号为zesty.使用apt-get命令安装软件时,有时候速度比较慢,有时候会失败.因此考虑用国内的镜像源更换下apt-get的默 ...

  3. 使用Squid部署代理服务

    Squid是Linux系统中最为流行的一款高性能代理服务软件,通常用作Web网站的前置缓存服务,能够代替用户向网站服务器请求页面数据并进行缓存.简单来说,Squid服务程序会按照收到的用户请求向网站源 ...

  4. 序列化 pickle shelve json configparser

    模块pickle(皮考) dumps(当破死)序列化. 把对象转化成bytes loads(楼死) 反序列化. 吧bytes转化成对象 dic = {"jay": "周杰 ...

  5. java urlrewrite实现伪静态化

    1.示例 http://www.onlyfun.com/goods/company.jsp?companyId=455326 ==> http://www.onlyfun.com/company ...

  6. numpy中int类型与python中的int

    [code] import numpy as np nparr = np.array([[1 ,2, 3, 4]]) np_int32 = nparr[0][0] # np_int=1 py_int ...

  7. CSS动画原理及硬件加速

    一.图层 图层即层叠上下文,具体概念和应用大家可以看我之前转自张鑫旭大神博客的<CSS层叠上下文和层叠顺序>,这里我们简单复习一下产生层叠上下文的原因. 1.根层叠上下文 指的是页面根元素 ...

  8. 全网最详细的Sublime Text 3的插件官方网站(图文详解)

    不多说,直接上干货! 全网最详细的Windows里下载与安装Sublime Text *(图文详解) 全网最详细的Sublime Text 3的激活(图文详解) 全网最详细的Sublime Text ...

  9. 【原创】贡献一个项目中用到的js身份证验证-超级准!!!

    前言 百度百科解释:身份证号码 首先贡献一个大神的链接:js验证身份证超准 代码 function checkIdcard(idcard) { var Errors = new Array( &quo ...

  10. java中this$0 this$1 this$2

    import java.lang.reflect.Field; public class Outer {//this$0 public class FirstInner {//this$1 publi ...