在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
摘要今天在园子里面有园友反馈关于[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(1000); Thread th2 = new Thread(() => { //这个地方你可能会有疑惑,但存在这种情况,比如你封装的dll,对其它开发人员不是可见的 //开发人员很有可能在他的逻辑中,加上一个lock保证方法同时被一个线程调用,但这时有其它的线程正在调用该方法, //但并没有释放,死锁了,那么在这里就不会被执行,除非上面的线程释放了lock锁定的对象。这里的lock也可以理解为一个标识,线程1被锁定的对象 测试 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(1000); 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 = 0; while (true) { Console.WriteLine("At work, do not disturb...,Thread id is " + Thread.CurrentThread.ManagedThreadId.ToString()); Thread.Sleep(1000); if (i == 5) { 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),因为无法保证你提供的方法,在外部类中使用的时候,开发人员会不会锁定当前对象。
这里只是说明lock(this)的问题,虽然极端。但开发中,不能保证不会发生。 2、最好使用私有的静态只读的锁对象,保证不会影响其他逻辑的正常执行。 3、尽量避免死锁的发生。 资料,如果仍然不明白可以参考下面的链接 非常感谢,@咕-咚 在上篇文章中,对demo提出的疑问,引发进一步的思考。当然,如果还有不妥的地方,欢迎指正,讨论。 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论