c#中lock作用,c#中lock

  c#中lock作用,c#中lock

  1.你为什么要上锁?你锁了什么?

  当我们使用线程的时候,最高效的方式当然是异步,也就是每个线程同时运行,不需要互相依赖和等待。然而,当不同的线程需要访问一个资源时,就需要一个同步机制。也就是说,在对同一个资源进行读写操作时,一定要使资源同时只被一个线程操作,这样才能保证每一个操作都是有效的、即时的,也就是保证其操作的原子性。Lock是C#中最常用的同步方法,其格式为lock(objectA){codeB}。

  Lock(objectA){codeB}看起来很简单,但它实际上有三个含义,这对于正确使用它是必不可少的:

  1.对象a是否已被锁定?那我就不锁了,不然就等到objectA发布。

  2.锁定后,在codeB执行期间,其他线程不能调用codeB或使用objectA。

  3.执行完codeB后释放objectA,codeB可以被其他线程访问。

  2.锁(这个)怎么了?

  让我们看一个例子:

  C1级

  {

  private bool死锁=true//这个方法使用了lock,我们希望lock的代码一次只能被一个线程访问。

  public void LockMe(对象o)

  {

  锁(储物柜)

  {

  while(陷入僵局)

  {

  死锁=(bool)o;

  控制台。WriteLine(Foo:我被锁定:();

  线程。睡眠(500);

  }

  }

  }

  //所有线程可以同时访问的方法

  public void DoNotLockMe()

  {

  控制台。WriteLine(我没有被锁定:));

  }

  }班级计划

  {

  静态void Main(string[] args)

  {

  C1 c1=新C1();

  //调用t1线程中的LockMe,并将deadlock设置为true(会发生死锁)

  线程t1=新线程(c1。lock me);

  t1。开始(真);

  线程。睡眠(100);

  //在主线程中锁定c1

  锁定(c1)

  {

  //调用未被锁定的方法

  c1。DoNotLockMe();

  //调用lock方法,尝试释放死锁。

  c1。LockMe(假);

  }

  }

  }

  程序运行结果如上图所示。在t1线程中,LockMe调用lock(this),这是主函数中的c1。此时,在主线程中调用lock(c1)时,要等t1中的lock块结束后才能访问c1,也就是所有c1相关的操作都无法完成,所以我们看到,即使是c1。DoNotLockMe()尚未执行。

  我们稍微修改一下C1的代码,保持mian()主函数中的代码不变:

  C1级

  {

  private bool死锁=true

  私有对象锁=新对象();

  //这个方法使用了lock,我们希望lock的代码一次只能被一个线程访问。

  public void LockMe(对象o)

  {

  锁(储物柜)

  {

  while(陷入僵局)

  {

  死锁=(bool)o;

  控制台。WriteLine(Foo:我被锁定:();

  线程。睡眠(500);

  }

  }

  }

  //所有线程可以同时访问的方法

  public void DoNotLockMe()

  {

  控制台。WriteLine(我没有被锁定:));

  }

  }

  程序运行结果如上图所示。这一次,我们使用一个私有成员作为锁柜,并且在LockMe中只锁定这个私有锁柜,而不是整个对象。此时再次运行程序,可以看到即使t1出现死锁,DoNotLockMe()仍然可以被主线程访问;LockMe()仍然不可访问,因为t1还没有释放其中锁定的锁。

  关键点:

  1.lock (this)的缺点是,一个线程(比如本例中的t1)通过执行使用 lock(this)的类的方法(比如本例中的LockMe())锁定一个对象后,整个对象就不能被其他线程(比如本例中的主线程)访问了——因为很多人在其他线程(比如本例中的主线程)使用这个类时会使用类似的方法。

  2.锁定的不仅仅是锁段中的代码,锁本身也是线程安全的。

  3.我们应该使用不影响其他操作的私有对象作为locker。

  4.使用lock时,锁定的对象(locker)必须是引用类型。如果是值类型的话,那么每次被锁的时候都会被装箱成一个新的引用对象(其实如果你用值类型的话,C#编译器(3.5.30729.1)编译的时候会报错)。

  C的值类型包括:结构(数值型、bool型、自定义结构)、枚举、可空型。C的引用类型包括:数组、用户定义的类、接口、委托、对象和字符串。

  因此,如果有如下定义:

  A级

  {

  }

  结构S

  {

  }

  int I;

  对象o;

  字符串str

  A A=new A();

  S S=new S();

  请注意下面的语法是正确的还是错误的。

  Lock(i){}//错误

  Lock(o){}//正确

  Lock(str){}//正确

  Lock(a){}//正确

  锁{}//错误

  Lock语句基本上使用Monitor。进入并监控。退出,也就是说,监控。使用lock(this)时执行Enter(this ),并监视。Exit(this)在花括号结束时执行。他的意义是什么?对于任何对象,所有方法的地址都放在其内存的第一部分。在第二部分,有一个索引,它指向CLR的SyncBlock缓存区中的一个SyncBlock。这是什么意思?也就是说,当您执行Monitor。Enter(Object),如果对象的索引值为负,则从SyncBlock缓存中选择一个SyncBlock,将其地址放入对象的索引中。这样,object标记的锁就完成了。如果其他线程想要执行监控。再次进入(object)操作,它们将得到object为正的索引并等待。直到索引变成负数,也就是线程使用Monitor。Exit(object)使索引为负。

  system . threading . monitor . enter(x);

  尝试

  {

  .

  }

  最后

  {

  system . threading . monitor . exit(x);

  }

  一些系统类提供专用于锁定的成员。例如,数组类型提供SyncRoot。许多集合类型也提供SyncRoot。和自定义类推荐私有只读静态对象,例如:

  私有静态只读对象obj=new object();

  为什么要设置为只读?这时,如果你改变锁代码段中obj的值,其他线程将不受阻碍,因为互斥的对象已经改变,而对象。ReferenceEquals将不可避免地返回false。

  其他参考连接:

  http://www.jb51.net/article/57220.htm

  http://www.2cto.com/kf/201110/108043.html

  http://www.csharpwin.com/csharpspace/12362r6119.shtml

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • 设计一个简单的C#控制台应用程序,C#控制台程序,C# 创建控制台应用程序
  • 深入解析windows第8版,深入解析C#(第4版)
  • 数组代码,c# 数组操作,C# 数组实例介绍(图文)
  • 学会C#要多久,学会c#要多久,c#学习之30分钟学会XAML
  • 回溯法01背包问题c,回溯法求解01背包问题伪代码,C#使用回溯法解决背包问题实例分析
  • xml文件转义字符,xml转意字符,C# XML中的转义字符操作
  • winform 进度条控件,c# 进度条使用
  • winform 进度条控件,c# 进度条使用,C#使用winform实现进度条效果
  • winform backgroundworker,c# isbackground
  • winform backgroundworker,c# isbackground,C# BackgroundWorker用法详解
  • lua与c#交互,lua c#
  • lua与c#交互,lua c#,ToLua框架下C#与Lua代码的互调操作
  • linq c#,linq原理 c#
  • linq c#,linq原理 c#,c#中LINQ的基本用法实例
  • java decimal保留两位小数,sql中decimal函数保留2位小数,C#中decimal保留2位有效小数的实现方法
  • 留言与评论(共有 条评论)
       
    验证码: