C#中Lock的用法

lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。

lock语句根本使用的就是Monitor.Enter和Monitor.Exit,也就是说lock(this)时执行Monitor.Enter(this),大括号结束时执行Monitor.Exit(this).他的意义在于什么呢,对于任何一个对象来说,他在内存中的第一部分放置的是所有方法的地址,第二部分放着一个索引,他指向CLR中的SyncBlock Cache区域中的一个SyncBlock.什么意思呢?就是说,当你执行Monitor.Enter(Object)时,如果object的索引值为负数,就从SyncBlock Cache中选区一个SyncBlock,将其地址放在object的索引中。这样就完成了以object为标志的锁定,其他的线程想再次进行Monitor.Enter(object)操作,将获得object为正数的索引,然后就等待。直到索引变为负数,即线程使用Monitor.Exit(object)将索引变为负数。

使用lock需要注意的地方:

1.lock不能锁定空值某一对象可以指向Null,但Null是不需要被释放的。(请参考:认识全面的null) 2.lock不能锁定string类型,虽然它也是引用类型的。因为字符串类型被CLR“暂留”

这意味着整个程序中任何给定字符串都只有一个实例,就是这同一个对象表示了所有运行的应用程序域的所有线程中的该文本。因此,只要在应用程序进程中的任何位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。因此,最好锁定不会被暂留的私有或受保护成员。 3.lock锁定的对象是一个程序块的内存边界 4.值类型不能被lock,因为前文标红字的“对象被释放”,值类型不是引用类型的

5.lock就避免锁定public 类型或不受程序控制的对象。 例如,如果该实例可以被公开访问,则 lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象。这可能导致死锁,即两个或更多个线程等待释放同一对象。出于同样的原因,锁定公共数据类型(相比于对象)也可能导致问题。 使用lock(this)的时候,类的成员变量的值可能会被不在临界区的方法改值了

应用场景:经常会应用于防止多线程操作导致公用变量值出现不确定的异常,用于确保操作的安全性

示例:

// statements_lock2.cs using System;

using System.Threading;

class Account {

private Object thisLock = new Object();

int balance;

Random r = new Random();

public Account(int initial)

{

balance = initial;

}

int Withdraw(int amount)

{

// This condition will never be true unless the lock statement

// is commented out:

if (balance < 0)

{

throw new Exception("Negative Balance");

}

// Comment out the next line to see the effect of leaving out

// the lock keyword:

lock(thisLock)

{

if (balance >= amount)

{

Console.WriteLine("Balance before Withdrawal :  " + balance);

Console.WriteLine("Amount to Withdraw        : -" + amount);

balance = balance - amount;

Console.WriteLine("Balance after Withdrawal  :  " + balance);

return amount;

}

else

{

return 0;

// transaction rejected

}

}

}

public void DoTransactions()

{

for (int i = 0; i < 100; i++)

{

Withdraw(r.Next(1, 100));

}

}

}

class Test {

static void Main()

{

Thread[] threads = new Thread[10];

Account acc = new Account(1000);

for (int i = 0; i < 10; i++)

{

Thread t = new Thread(new ThreadStart(acc.DoTransactions));

threads[i] = t;

}

for (int i = 0; i < 10; i++)

{

threads[i].Start();

}

}

}

C#中Lock的用法

时间: 2024-10-04 19:56:55

C#中Lock的用法的相关文章

c#多线程中Lock()关键字的用法小结

本篇文章主要是对c#多线程中Lock()关键字的用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待. 每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数.这可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生.

c#初学-多线程中lock用法的经典实例

本文转载自:http://www.cnblogs.com/promise-7/articles/2354077.html 一.Lock定义     lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断.它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待.这是通过在代码块运行期间为给定对象获取互斥锁来实现的. 在多线程中,每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数.这可能带来的问

mysql中event的用法详解

一.基本概念mysql5.1版本开始引进event概念.event既“时间触发器”,与triggers的事件触发不同,event类似与linux crontab计划任务,用于时间触发.通过单独或调用存储过程使用,在某一特定的时间点,触发相关的SQL语句或存储过程. 二.适用范围对于每隔一段时间就有固定需求的操作,如创建表,删除数据等操作,可以使用event来处理. 例如:使用event在每月的1日凌晨1点自动创建下个月需要使用的三张表. 三.使用权限单独使用event调用SQL语句时,查看和创建

C#中lock死锁实例教程

这篇文章主要介绍了C#中lock死锁的用法,对于共享资源的访问及C#程序设计的安全性而言,有着非常重要的意义!需要的朋友可以参考下 链接:http://www.jb51.net/article/54309.htm 在c#中有个关键字lock,它的作用是锁定某一代码块,让同一时间只有一个线程访问该代码块,本文就来谈谈lock关键字的原理和其中应注意的几个问题: lock的使用原型是: ? 1 2 3 4 lock(X) {   //需要锁定的代码.... } 首先要明白为什么上面这段话能够锁定代码

Oracle 中 decode 函数用法

Oracle 中 decode 函数用法 含义解释:decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值) 该函数的含义如下:IF 条件=值1 THEN RETURN(翻译值1)ELSIF 条件=值2 THEN RETURN(翻译值2) ......ELSIF 条件=值n THEN RETURN(翻译值n)ELSE RETURN(缺省值)END IFdecode(字段或字段的运算,值1,值2,值3) 这个函数运行的结果是,当字段或字段的运算的值等于值1时,该函数返回值

linux中快捷键的用法

linux中快捷键的用法 1.1 常见快捷键 ctrl + a 把光标移动到行首 ctrl + e 把光标移动到行尾 ctrl + c 撤销当前的操作=cancel ctrl + d logout命令(当前行没有任何内容,退出当前用户),删除光标所在位置后面的一个符号,文本 ctrl + l(小写字母L)清除屏幕内容 ctrl +u 剪切光标所在位置到行首内容 ctrl +k 剪切光标所在位置到行尾内容 ctrl +y 粘贴 ctrl + r search搜索历史命令,继续搜索,查找历史命令 

thinkphp中I(&quot;parm&quot;)用法的注意事项

php中用来传输的方式有两种$_GET 和 $_POST, thinkphp 提供了一种兼容两中传输方式的做法I(“param”) 但是请注意:在使用php中的函数时需要传入参数时不能用I(“parm”),必须使用采用的传输方式$_GET 或 $_POST传入,否则出错 thinkphp中I("parm")用法的注意事项,布布扣,bubuko.com

ASP.NET在实际开发中验证码的用法

在网上有看到很多关于验证码的代码,很多都只是生成一张验证码图片,然而在实际登陆验证模块,验证码要怎么添加进去或者说怎么运用.和实际项目开发中要怎么使用验证码,我自己总结了几点. 一.在实际开发登陆模块的验证码,程序员是将验证码的文本值(字符串)存在Session中的,然后在登陆验证的时候,通过Session取值进行判断的,这样效率会高很多. 二.然而在写验证码的时候要想通过Session存值,就必须实现System.Web.SessionState.IRequiresSessionState这个

objective-c 中随机数的用法 (3种:arc4random() 、random()、CCRANDOM_0_1() )

1.随机数的使用      1).arc4random() 比较精确不需要生成随即种子 使用方法 : 通过arc4random() 获取0到x-1之间的整数的代码如下: int value = arc4random() % x; 获取1到x之间的整数的代码如下: int value = (arc4random() % x) + 1; 2).CCRANDOM_0_1() cocos2d中使用 ,范围是[0,1] 使用方法: float random = CCRANDOM_0_1() * 5; //