C# 说说lock

一、MSDN的定义

lock 语句获取给定对象的互斥 lock,执行语句块,然后释放 lock。 持有 lock 时,持有 lock 的线程可以再次获取并释放 lock。 阻止任何其他线程获取 lock 并等待释放 lock。lock 关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区。 如果其他线程尝试进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。

lock 语句具有以下格式

lock (x)
{
    // Your code...
}

 其中 x引用类型的表达式。 它完全等同于

object __lockObj = x;
bool __lockWasTaken = false;
try
{
    System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
    // Your code...
}
finally
{
    if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}

 

二、lock原理


lock 关键字在块的开始处调用Monitor.Enter,而在块的结尾处调用Monitor.Exit。通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:
如果实例可以被公共访问,将出现 lock (this) 问题。

如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。

锁定字符串尤其危险,因为字符串被公共语言运行库 (CLR)“暂留”。 这意味着整个程序中任何给定字符串都只有一个实例,进程中使用同一字符串的任何其他代码都将共享同一个锁,所以出现 lock("myLock") 问题。最佳做法是定义 private 对象来锁定, 或 private static 对象变量来保护所有实例所共有的数据。在 lock 语句的正文不能使用 等待 (await)关键字。

为什么锁的对象是私有的呢?还是以厕所为例子吧,私有就好比,这把锁只有你能访问到,而且最好这把锁不会因为外力而有所改变,别人访问不到,这样才能保证你进去了,别人就进不去了,如果是公有的,就好比你蹲位小单间的锁不是安装在里面而是安装在外边的,别人想不想进就不是你所能控制的了,这样也不安全。

三、使用lock实现单例模式

class SingletonClass
    {
        private static SingletonClass _instance = null;
        private static readonly object syncRoot = new object();   

        private SingletonClass()
        { 
        }

        public static SingletonClass GetInstance()
        {
            if (_instance == null)
            {
                lock (syncRoot)
                {
                    if (_instance == null)
                    {
                        _instance = new SingletonClass();
                    }
                }
            }
            return _instance;
        }
    }

在上述代码中出现“If - Lock - If”结构模式,即双重检查锁定的双重判断机制:

if (_instance == null)   //第一重判断,先判断实例是否存在,不存在再加锁处理
            {
                lock (syncRoot)   //加锁,在某一时刻只允许一个线程访问
                {
                    if (_instance == null)   //第二重判断: 第一个线程进入Lock中执行创建代码,第二个线程处于排队等待状态,当第二个线程进入Lock后并不知道实例已创建,将会继续创建新的实例
                    {
                        _instance = new SingletonClass();
                    }
                }
            }

下面几点需要注意的地方

1、lock的是引用类型的对象,string类型除外。

2、lock推荐的做法是使用静态的、只读的、私有的对象。

3、保证lock的对象在外部无法修改才有意义,如果lock的对象在外部改变了,对其他线程就会畅通无阻,失去了lock的意义。

 

参考:

https://www.cnblogs.com/goldendragon/p/9913600.html

https://www.cnblogs.com/youmingkuang/p/9987672.html

https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/lock-statement?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DZH-CN%26k%3Dk(lock_CSharpKeyword)%3Bk(TargetFrameworkMoniker-.NETFramework%2CVersion%3Dv4.5)%3Bk(DevLang-csharp)%26rd%3Dtrue

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值