C#的Lock
程序员文章站
2022-04-15 10:49:07
有时候在编写线程并发的时候需要考虑异步和同步的问题。有些资源只能是一个线程访问,其他的线程在这个线程没有释放资源前不能访问。类似于操作系统中临界资源的访问。C#Lock包裹的代码块具有原子操作的特性(要么执行到结束为止,要么不执行)。 举个列子:银行账户的余额就是典型的临界资源的问题,假如原本有10 ......
有时候在编写线程并发的时候需要考虑异步和同步的问题。有些资源只能是一个线程访问,其他的线程在这个线程没有释放资源前不能访问。类似于操作系统中临界资源的访问。c#lock包裹的代码块具有原子操作的特性(要么执行到结束为止,要么不执行)。
举个列子:银行账户的余额就是典型的临界资源的问题,假如原本有1000,你的情妇a,b先后打500给你。a打500的这个操作是一个线程,从数据库取出余额的值累加正准备写回数据库的时候,由于某种原因(时间片用完、来了更高的优先级的线程)阻塞,这时候b又给你打500,他得到余额依然是1000,累加后写回数据库1500到手。这时刚才被阻塞的线程又获得执行权,将1500写回数据库。你莫名奇妙少了500,回去找情妇理论是没有结果的,银行系统的锅。
lock可以运用在单列模式上。刚开始我一直纳闷lock括号里面究竟写什么,经同学指点。大概是任意不会改变的对象(里面写一个固定的字符串”999“也可以)
那个对象是一把锁。它会把钥匙给第一个访问它的进程,如果进程完事就上交钥匙。有且只有一把钥匙,实现了原子操作
using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
namespace testlock
{
class testthread
{
private static testthread instance;
private static object obj = new object();
private testthread() { }
public static void getinstance()
{
if (instance == null)//先判断,异步
{
lock (obj)//任意不改变对象
{
if (instance == null)//同步
{
console.writeline("初始化");
instance = new testthread();
}
}
}
}
}
}
thread t1 = new thread(testthread.getinstance);
thread t2 = new thread(testthread.getinstance);
thread t3 = new thread(testthread.getinstance);
t1.start();
t2.start();
t3.start();
结果是只打印一行初始化,如果没有lock包裹那块代码那么结果会有三行初始化。因为,线程都会遇到if (instance == null)真