文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>关于lock一点总结

关于lock一点总结

时间:2010-11-22  来源:古古怪怪


MSDN关于lock说明:
    lock确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。

    通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:

    如果实例可以被公共访问,将出现 lock (this) 问题。

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

    由于进程中使用同一字符串的任何其他代码都将共享同一个锁,所以出现 lock(“myLock”) 问题。

关于lock(“myLock”)的MSDN解释:
    锁定字符串尤其危险,因为字符串被公共语言运行库 (CLR)“暂留”。 这意味着整个程序中任何给定字符串
    都只有一个实例,就是这同一个对象表示了所有运行的应用程序域的所有线程中的该文本。因此,只要在应用
    程序进程中的任何位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。

关于lock (typeof (MyType))与锁定字符串lock(“myLock”)一样,范围太广了。

 

但lock (this)会怎样出现问题,让本人这种水平的小菜看的有些云里雾里,估计高手应该不会这样。

经过一些研究,个人总结的使用lock时候两种情况:


1.同一个对象,不同线程。lock (this) 不会出现问题的例子

示例代码1
 1 class MyMainClass
2 {
3 private static readonly object lockHelper = new object();
4 private static int num = 0; //记录不同线程操作的次数
5 private int count = 0; //记录每个对象执行次数
6
7 static void Main()
8 {
9 MyMainClass c1 = new MyMainClass();
10
11 Thread myThread1 = new Thread(new ThreadStart(c1.DoSomething));
12 myThread1.Name = "FirstThread";
13 myThread1.Start();
14
15 Thread myThread2 = new Thread(new ThreadStart(c1.DoSomething));
16 myThread2.Name = "SecondThread";
17 myThread2.Start();
18
19 while (num < 100)
20 {
21 //其他一些操作
22 }
23
24 myThread1.Abort();
25 myThread2.Abort();
26
27 Console.WriteLine("C1 count: {0}", c1.count);
28 Console.ReadLine();
29
30 }
31
32 public void DoSomething()
33 {
34 //此处可以用this,或者也可以用lockHelper
35 lock (this)
36 {
37 while (num < 100)
38 {
39 num++;
40 Console.WriteLine("{0} add value: {1}", Thread.CurrentThread.Name, num);
41 count++;
42 }
43 }
44 }
45 }
46
47

 

 

2.不同对象,不同线程。lock (this) 会出现问题的例子

示例代码2
class MyMainClass
{
private static readonly object lockHelper = new object();
private static int num = 0; //记录不同线程操作的次数
private int count = 0; //记录每个对象执行次数

static void Main()
{
MyMainClass c1
= new MyMainClass();
MyMainClass c2
= new MyMainClass();

Thread myThread1
= new Thread(new ThreadStart(c1.DoSomething));
myThread1.Name
= "FirstThread";
myThread1.Start();

Thread myThread2
= new Thread(new ThreadStart(c2.DoSomething));
myThread2.Name
= "SecondThread";
myThread2.Start();

while (num < 100)
{
//其他一些操作
}

myThread1.Abort();
myThread2.Abort();

Console.WriteLine(
"C1 count: {0}", c1.count);
Console.WriteLine(
"C2 count: {0}", c2.count);

Console.ReadLine();

}

public void DoSomething()
{
//lock (this)
//此处只可以用lockHelper,若用this则锁不住
lock (lockHelper)
{
while (num < 100)
{
num
++;
Console.WriteLine(
"{0} add value: {1}", Thread.CurrentThread.Name, num);
count
++;
}
}

}
}

 

 

解释:
    private static readonly object lockHelper = new object();
    私有 private:确保只有该类的对象内部可以访问
    静态 static: 确保锁定的内容只有一份,不会出现锁不住的情况
    只读 readonly: 这是因为如果在lock代码段中改变lockHelper的值,其它线程就畅通无阻了,因为互斥锁的对象变了,object.ReferenceEquals必然返回false

注意:lock锁的对象不能是null,否则引发异常。
lock在IL代码中实际上是执行:

 try
{
Monitor.Enter(lockHelper);
//
}
finally
{
Monitor.Exit(lockHelper);
}

       替代lock的Monitor类,它的静态方法Enter(object obj)有一个异常类型ArgumentNullException

 

第一篇小随笔,思路及代码不严谨之处请多多包涵。欢迎指正,不胜感激!

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载