C# 说说lock到底锁谁?(2)
摘要
今天在园子里面有园友反馈关于[C#基础]说说lock到底锁谁?文章中lock(this)的问题。后来针对文章中的例子,仔细想了一下,确实不准确,才有了这篇文章的补充,已经对文章中的demo进行修改。
lock(this)
一个例子
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace LockTest
{
class Program
{
static void Main(string[] args)
{
TestLock testlock = new TestLock();
Thread th = new Thread(() =>
{
//模拟死锁:造成死锁,使lock无法释放,在i=5时,跳出死循环,释放lock
testlock.DoWorkWithLock();
});
th.Start();
Thread.Sleep();
Thread th2 = new Thread(() =>
{
//这个地方你可能会有疑惑,但存在这种情况,比如你封装的dll,对其它开发人员不是可见的
//开发人员很有可能在他的逻辑中,加上一个lock保证方法同时被一个线程调用,但这时有其它的线程正在调用该方法,
//但并没有释放,死锁了,那么在这里就不会被执行,除非上面的线程释放了lock锁定的对象。这里的lock也可以理解为一个标识,线程1被锁定的对象
//是否已经被释放,
//如果没有释放,则无法继续访问lock块中的代码。
lock (testlock)
{
// 如果该对象中lock(this)不释放(testlock与this指的是同一个对象),则其它线程如果调用该方法,则会出现直到lock(this)释放后才能继续调用。
testlock.MotherCallYouDinner();
testlock.DoWorkWithLock();
}
});
th2.Start();
Console.Read();
}
} class TestLock
{
public static readonly object objLock = new object();
/// <summary>
/// 该方法,希望某人在工作的时候,其它人不要打扰(希望只有一个线程在执行)
/// </summary>
/// <param name="methodIndex"></param>
public void DoWorkWithLock()
{
//锁当前对象
lock (this)
{
Console.WriteLine("lock this");
int i = ;
while (true)
{
Console.WriteLine("At work, do not disturb...,Thread id is " + Thread.CurrentThread.ManagedThreadId.ToString());
Thread.Sleep();
if (i == )
{
break;
}
Console.WriteLine(i.ToString());
i++;
}
}
Console.WriteLine("lock dispose");
}
public void MotherCallYouDinner()
{
Console.WriteLine("Your mother call you to home for dinner.");
}
}
}
测试

demo说明:main方法中,创建了一个对象testlock对象,线程1执行该对象的DoWorkWithLock方法,因为死锁(5s后释放),造成lock(this)无法释放,则导致了方法MotherCallYouDinner,DoWorkWithLock在线程2中无法被调用,直到lock(this)释放,lock(testlock)才能继续执行,可以这么理解,由于锁定的同一个对象,线程1释放了锁定的对象,其它线程才能访问。
lock(static readonly object)
那么通过lock(static object)方式呢,能不能保证lock块内的方法,同时只被一个线程执行呢,并且线程2能访问到MotherCallYouDinner方法。而不像上面出现的那种情况,如果不释放lock(this),导致线程2都无法执行代码逻辑。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace LockTest
{
class Program
{
static void Main(string[] args)
{
TestLock testlock = new TestLock();
Thread th = new Thread(() =>
{
//模拟死锁:造成死锁,使lock无法释放,在i=5时,跳出死循环,释放lock
testlock.DoWorkWithLock();
});
th.Start();
Thread.Sleep();
Thread th2 = new Thread(() =>
{ lock (testlock)
{
testlock.MotherCallYouDinner();
testlock.DoWorkWithLock();
}
});
th2.Start();
Console.Read();
}
} class TestLock
{
public static readonly object objLock = new object();
/// <summary>
/// 该方法,希望某人在工作的时候,其它人不要打扰(希望只有一个线程在执行)
/// </summary>
/// <param name="methodIndex"></param>
public void DoWorkWithLock()
{
//锁
lock (objLock)
{
Console.WriteLine("lock this");
int i = ;
while (true)
{
Console.WriteLine("At work, do not disturb...,Thread id is " + Thread.CurrentThread.ManagedThreadId.ToString());
Thread.Sleep();
if (i == )
{
break;
}
Console.WriteLine(i.ToString());
i++;
}
}
Console.WriteLine("lock dispose");
}
public void MotherCallYouDinner()
{
Console.WriteLine("Your mother call you to home for dinner.");
}
}
}
测试

可以看到,将lock(this)更换为锁定私有的静态对象,线程2执行了,首先输出了“Your mother call you to home for dinner.”,同时实现了DoWorkWithLock方法中lock的代码块当前只被一个线程执行,直到lcok(objlock)被释放。因为锁定的对象,外部不能访问,线程2不再关心lock(this)是不是已经释放,都会执行,当然也保证了方法DoWorkWithLock同时被一个线程访问。
总结
1、避免使用lock(this),因为无法保证你提供的方法,在外部类中使用的时候,开发人员会不会锁定当前对象。
通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:
如果实例可以被公共访问,将出现 lock (this) 问题。
如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。
由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。
最佳做法是定义 private 对象来锁定, 或 private static 对象变量来保护所有实例所共有的数据。
这里只是说明lock(this)的问题,虽然极端。但开发中,不能保证不会发生。
2、最好使用私有的静态只读的锁对象,保证不会影响其他逻辑的正常执行。
3、尽量避免死锁的发生。
资料,如果仍然不明白可以参考下面的链接
来源:http://www.cnblogs.com/wolf-sun/p/8405541.html
C# 说说lock到底锁谁?(2)的更多相关文章
- [C#基础]说说lock到底锁谁?
写在前面 最近一个月一直在弄文件传输组件,其中用到多线程的技术,但有的地方确实需要只能有一个线程来操作,如何才能保证只有一个线程呢?首先想到的就是锁的概念,最近在我们项目组中听的最多的也是锁谁,如何锁 ...
- C# 说说lock到底锁谁?(1)
写在前面 最近一个月一直在弄文件传输组件,其中用到多线程的技术,但有的地方确实需要只能有一个线程来操作,如何才能保证只有一个线程呢?首先想到的就是锁的概念,最近在我们项目组中听的最多的也是锁谁,如何锁 ...
- [C#基础]说说lock到底锁谁?(补充与修改)
摘要 今天在园子里面有园友反馈关于[C#基础]说说lock到底锁谁?文章中lock(this)的问题.后来针对文章中的例子,仔细想了一下,确实不准确,才有了这篇文章的补充,已经对文章中的demo进行修 ...
- 说说lock到底锁谁(II)?
摘要 今天在园子里面有园友反馈关于[C#基础]说说lock到底锁谁?文章中lock(this)的问题.后来针对文章中的例子,仔细想了一下,确实不准确,才有了这篇文章的补充,已经对文章中的demo进行修 ...
- 说说lock到底锁谁(I)?
写在前面 最近一个月一直在弄文件传输组件,其中用到多线程的技术,但有的地方确实需要只能有一个线程来操作,如何才能保证只有一个线程呢?首先想到的就是锁的概念,最近在我们项目组中听的最多的也是锁谁,如何锁 ...
- 说说lock到底要锁谁?
波安搬... http://www.cnblogs.com/wolf-sun/p/4209521.html ---------------------------------------------- ...
- Coarse-Grained lock 粗粒度锁
用一个锁Lock一组相关的对象 有时,需要按组来修改多个对象. 这样,在需要锁住其中一个的时候,必须连带地将其他的对象都上锁. 为每一个对象都加上一个锁是很繁琐的. 粗粒度锁是覆盖多个对象的单个锁. ...
- Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁
(1)synchronized 是互斥锁: (2)ReentrantLock 顾名思义 :可重入锁 (3)ReadWriteLock :读写锁 读写锁特点: a)多个读者可以同时进行读b)写者必须互斥 ...
- JUC--Callable 以及Lock同步锁
/** * 一.创建执行线程的方式三:实现Callable接口.相较于实现Runnable接口方式,方法可以有返回值,并且可以抛出异常 * 二.callable 需要FutureTask实现类的支持. ...
随机推荐
- properties文件读取工具类
项目中防止硬编码,经常会将一些与业务相关的数据存在properties文件中,根据不同的key加载不同的数据,所以就会有读取properties文件的东西,这篇文章仅为了以后copy方便写的. 1.添 ...
- 我也来----xia bi bi 一下----微信小程序
工作刚到一阶段 就看了看微信小程序 自己做了个小dome 主要是为了让我女朋友能够学习做菜! 然而悲催的发现我根本没有App ID 不说快了 直接上图 个人感觉开发起来还是很简单的. 对着AP ...
- linux --mariadb/redis数据库篇
mariadb ---磁盘型数据库 基础安装 配置好yum源后,软件就可以通过配置的yum源进行安装,按理来讲安装mysql直接通过 yum install mariadb -y 便可安装,但 ...
- 线程同步-SpinWait
这次将描述如何不适用内核模式的方式来使线程等待.SpinWait,它是一个混合同步构造,被设计为使用用户模式等待一段时间,然后切换到内核模式以节省CPU时间. 代码Demo: using System ...
- spark streaming集成kafka
Kakfa起初是由LinkedIn公司开发的一个分布式的消息系统,后成为Apache的一部分,它使用Scala编写,以可水平扩展和高吞吐率而被广泛使用.目前越来越多的开源分布式处理系统如Clouder ...
- 10大必备的Intellij插件,大幅提高你的工作效率
转自: https://blog.csdn.net/qq1404510094/article/details/80379375 1. .ignore 生成各种ignore文件,一键创建git igno ...
- VUE 全局变量的几种实现方式
最近在学习VUE.js 中间涉及到JS全局变量,与其说是VUE的全局变量,不如说是模块化JS开发的全局变量. 1.全局变量专用模块 就是以一个特定模块来组织管理这些全局量,需要引用的地方导入该模块便好 ...
- 关于什么是SpringMVC,和SpringMVC基于xml配置、注解配置、纯注解配置
首先我们先要了解一下,什么是SpringMVC? SpringMVC是Spring框架内置的MVC的实现.SpringMVC就是一个Spring内置的MVC子框架,也就是说SpringMVC的相关包都 ...
- 要学的javaee技术
mybatis.hibernate.spirng MVC.freemarker.zookeeper.dubbo.quartz的技术框架:NoSQL技术ehcache.memcached.redis等: ...
- 开发流程(Vue)
1.当你拿到一个需求时,先不要着急完成静态页面 2.重点观察数据结构,进行数据的分析,包括前端所需要的数据类型从而进行数据类型定义(如果是前后端分离的情况下,建议不要考虑前端数据和数据库的数据类型对应 ...