C# lock线程锁的用法
作者:大花爱编程
一、lock的作用
Lock可以看成在操作系统中的临界区,Lock区域内的代码表示临界区,使得同一时间只有一个线程能够进入Lock所包含的函数中,实现原子操作,保护同一资源只有一个线程进行修改,实现不同线程中数据的同步。
未进入Lock的线程将被阻塞等待,直到Lock锁被打开才唤醒其中一个进入,并且进行上锁
(总的来说Lock在多线程的运行中可以保证数据安全,对于保护的区域只允许一个线程使用!)
二、lock的基础使用
private Object thisLock = new Object();//创建对象锁 或者 private static readonly object thisLock = new object(); lock (thisLock) { // Critical code section }
注意事项:
- 需要注意的是首先创建的对象锁,应该是不同线程能够访问的同一个对象,因此至少应该是在类中是全局的,不应为局部变量。
- 为了实现全局的对象锁,可以使用static,例:private static Object thisLock = new Object();//创建对象锁
- 结合自己线程的运行特性,选择正确的对象锁
三、lock(this)的用法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Lock测试 { class Program { static void Main(string[] args) { C1 c1 = new C1(); //在t1线程中调用LockMe,并将deadlock设为true(将出现死锁) Thread t1 = new Thread(c1.LockMe); t1.Start(true); Thread.Sleep(100); //在主线程中lock c1 lock (c1) { //调用没有被lock的方法 c1.DoNotLockMe(); //调用被lock的方法,并试图将deadlock解除 c1.LockMe(false); } Console.Read(); } } class C1 { private bool deadlocked = true; //这个方法用到了lock,我们希望lock的代码在同一时刻只能由一个线程访问 public void LockMe(object o) { lock (this) { while (deadlocked) { deadlocked = (bool)o; Console.WriteLine("Foo: I am locked :("+o); Thread.Sleep(500); } } } //所有线程都可以同时访问的方法 public void DoNotLockMe() { Console.WriteLine("I am not locked :)"); } } }
在这个代码中,出现了两个lock锁,在C1中有一个锁,lock(this)主要是对LockMe方法进行上锁,在主要线程中又有一个Lock锁,主要是Lock(c1),该代码中,lock(this)其实就是把C1的实例c1当钥匙拿走,导致主线程后的lock(c1)无法继续执行。
当我们将lock的钥匙修改,如下:
private bool deadlocked = true; private object locker = new object(); //这个方法用到了lock,我们希望lock的代码在同一时刻只能由一个线程访问 public void LockMe(object o) { lock (locker) { while (deadlocked) { deadlocked = (bool)o; Console.WriteLine("Foo: I am locked :("+o); Thread.Sleep(500); } } } //所有线程都可以同时访问的方法 public void DoNotLockMe() { Console.WriteLine("I am not locked :)"); } } }
我们可以发现,就可以继续执行
总结:
1. lock(this)的缺点就是在一个线程(例如本例的t1)通过执行该类的某个使用"lock(this)"的方法(例如本例的LockMe())锁定某对象之后, 导致整个对象无法被其他线程(例如本例的主线程)访问 - 因为很多人在其他线程(例如本例的主线程)中使用该类的时候会使用类似lock(c1)的代码。
2. 锁定的不仅仅是lock段里的代码,锁本身也是线程安全的。
3. 我们应该使用不影响其他操作的私有对象作为locker。
4. 在使用lock的时候,被lock的对象(locker)一定要是引用类型的,如果是值类型,将导致每次lock的时候都会将该对象装箱为一个新的引用对象(事实上如果使用值类型,C#编译器(3.5.30729.1)在编译时就会给出一个错误)。
参考文献:
C# 关于线程锁lock的使用方法_c# lock方法-CSDN博客
C#线程锁(Lock)_c# lock_月光在发光的博客-CSDN博客
到此这篇关于C# lock线程锁的用法的文章就介绍到这了,更多相关C# lock线程锁 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!