关于lock

一直以来对于lock关键字的用法都存有疑惑,也从网上看到很多关于他的资料包括MSDN,无奈MSDN讲述的真是让人上火。今天决定小小研究一下

一直都知道lock是锁定某一变量从而实现对某一代码段的独占执行。

但是对于lock(this)、lock(typeof(类名))、lock(字符串)、lock(公有变量) lock(私有变量) 有什么不同 却很是模糊

我假定了这样一种场景:某个时刻,只允许一个客户在打电话

定义一个客户类

代码1:(lock(this))

 

 
  
/// 定义一个Custmer类,要求某一时间,只允许一个客户在打电话
public class Custmer
{
public Custmer()
{
}
public Custmer( string name)
{
_name
= name;
}
/// 某一时刻只允许一个客户在打电话
public void getPhone()
{
lock ( this )
{

for ( int i = 0 ; i < 10 ; i ++ )
{
Console.WriteLine(Thread.CurrentThread.Name
+ " 正在跟客户在通话 " );
Thread.Sleep(
1000 );
}

}
}
}

在主函数中调用,先实例化一个Custmer 实例

 

 
  
static void Main( string [] args)
{
Custmer c
= new Custmer();
Thread t1
= new Thread( new ThreadStart(c.getPhone));
t1.Name
= " t1 " ;
Thread t2
= new Thread( new ThreadStart(c.getPhone));
t2.Name
= " t2 " ;
t1.Start();

t2.Start();
Console.Read();

}

 

 

可以预先分析一下结果,因为用的是lock(this),而this这时候代表的是实例c,当其中一个线程在使用的时候,另一个线程是不能使用的。也就是说,结果应该是其中一个线程先使用,另一个再使用,而不是交替使用。

运行结果1:

 

 

 跟预想的结果一样,但是如果是多个客户实例呢,结果有怎样

代码2:

代码
 
   
static void Main( string [] args)
{
// 这里我实例化了两个客户类
Custmer c = new Custmer();
Custmer c2
= new Custmer();

// 线程1去接通c的电话
Thread t1 = new Thread( new ThreadStart(c.getPhone));
t1.Name
= " t1 " ;
// 线程2去接通c2的电话
Thread t2 = new Thread( new ThreadStart(c2.getPhone));
t2.Name
= " t2 " ;
t1.Start();

t2.Start();
Console.Read();

}

再预想一下结果,对于线程t1,跟客户c接通电话,此时lock(this)中的this是当前实例c。同理,对于线程t2,this是实例c2.这样lock(this)锁定的是不同的对象,所以无法达到某一时刻,只有一个客户在电话。也就是说,两个线程会交替执行。

执行结果2:

与预想结果一样。从这里我们知道,lock(this)存在多个实例间互斥不能实现的问题,原因在于this指向的是不同的实例

另外在有的地方说lock(this)可能会造成死锁,所谓的死锁,无非就是一个线程长期锁定this不释放。 可能是lock锁定的代码段是个死循环,也可能你在一个死循环里调用lock锁定的代码段。总之是没有释放锁定对象。

 

Lock(typeof(类名))

我重新定义了一个sales类,用来在Customer类中锁定它

sales类

 

 
  
public class sales
{
public sales( string name)
{
_name
= name;
}
string _name;

public string Name
{
get { return _name; }
set { _name = value; }
}

}

 

Customer类改写如下:

 
  
public class Custmer
{
public Custmer()
{
}
public Custmer( string name)
{
_name
= name;
}
string _name;

public string Name
{
get { return _name; }
set { _name = value; }
}


public void getPhone()
{
lock ( typeof (sales)) // 关键是这里
{

for ( int i = 0 ; i < 10 ; i ++ )
{
Console.WriteLine(Thread.CurrentThread.Name
+ " 正在跟客户在通话 " );
Thread.Sleep(
1000 );
}

}
}
}

我们在主函数中,调用如Lock(this)的单个实例的情况,我们会发现,实现了互斥。多个实例的情况也实现了互斥。但是又有了新的问题。因为我们锁定的是类本身,所以如果有一个地方是在使用类,那么其他地方就不能使用该类,这样的限制过于苛刻。

 

3.Lock(字符串)

这个就更好玩了,他是实现了绝对的互斥。只要字符串内容相同,就能引起程序挂起。原因是在.NET中,字符串会被暂时存放,如果两个变量的字符串内容相同的话,.NET会把暂存的字符串对象分配给该变量。所以如果有两个地方都在使用lock(字符串)的话,它们实际锁住的是同一个对象。

那我们看一下代码和执行结果

代码:

 

 
  
public class Custmer
{
string flag = " ATually " ; // 定义了一个字符串变量
public Custmer()
{
}
public Custmer( string name)
{
_name
= name;
}

string _name;

public string Name
{
get { return _name; }
set { _name = value; }
}


public void getPhone()
{
lock (flag) // 关键是这里
{

for ( int i = 0 ; i < 10 ; i ++ )
{
Console.WriteLine(Thread.CurrentThread.Name
+ " 正在跟客户在通话 " );
Thread.Sleep(
1000 );
}

}
}
}

多个实例的情况下的执行结果也实现了互斥。

对于Lock(共有变量)和Lock(私有变量)基本效果都一样,但是都会出现对于多个实例都无法实现互斥。

因此,微软推荐使用私有静态变量作为锁定的变量。但是个人觉得与锁定类和锁定字符串 没有什么不同。

以上只是个人浅见,如有错的地方,请不吝赐教,谢谢。

转载于:https://www.cnblogs.com/ATually/archive/2010/12/21/1912992.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值