你好,游客 登录
背景:
阅读新闻

[C#基础]说说lock到底锁谁?(补充与修改)

[日期:2018-02-03] 来源:博客园_Wolfy  作者: [字体: ]

摘要

今天在园子里面有园友反馈关于 [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 (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 = 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.");
}
}
}

测试

demo说明:main方法中,创建了一个对象testlock对象,多线程执行该对象的DoWorkWithLock方法,因为死锁(5s后释放),造成lock(this)无法释放,则导致了方法DoWorkWithLock在其它线程中无法被调用,直到lock(this)释放,其它线程才能访问。比如上面线程2注释说明的一种情况,如果你程序集中加了锁,然后当前使用你封装程序集的人,也为该对象加了锁,由于线程1死锁,则无法释放lock,则线程2一直处于等待状态,无法执行线程2的MotherCallYouDinner方法,虽然可以保证DoWorkWithLock同时只被一个线程访问,但不应该影响其他逻辑的执行。如果发生了死锁,线程2一只处于等待状态。

lock(static readonly object)

那么通过lock(static object)方式呢,能不能保证技能保证lock块内的方法,同时只被一个线程执行,又不影响其他的逻辑呢?

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.");
}
}
}

测试

可以看到,线程2执行了,首先输出了“Your mother call you to home for dinner.”,同时实现了DoWorkWithLock方法中lock的代码块当前只被一个线程执行,直到lcok(objlock)被释放,又不影响其它的逻辑执行。

总结

1、避免使用lock(this),因为无法保证你提供的方法,在外部类中使用的时候,开发人员会不会锁定当前对象。而且lock(this)只对当前对象有效,如果多个对象之间就达不到同步的效果。

2、最好使用私有的静态只读的锁对象,保证不会影响其他逻辑的正常执行。

3、尽量避免死锁的发生。

资料,如果仍然不明白可以参考下面的链接

Why is lock(this) {…} bad?

收藏 推荐 打印 | 录入:Cstor | 阅读:
相关新闻      
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数
点评:
       
评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款