`
yueue
  • 浏览: 50441 次
  • 性别: Icon_minigender_1
  • 来自: 西安
最近访客 更多访客>>
社区版块
存档分类
最新评论

.NET中的lock

    博客分类:
  • .NET
阅读更多

lock 关键字可将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。此语句的形式如下:
lock(expression) statement_block
其中:
expression
指定要锁定的对象。expression 必须是引用类型。
通常,如果要保护实例变量,则 expression 为 this;如果要保护 static 变量(或者如果临界区出现在给定类的静态方法中),则 expression 为 typeOf (class)。
statement_block
临界区的语句。
备注
lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入一个锁定代码,则它将在释放该对象前一直等待(块)。
8.12 lock 语句对 lock 进行了讨论。
示例 1
下例显示的是在 C# 中使用线程的简单示例。
// statements_lock.cs
using System;
using System.Threading;

class ThreadTest
{
public void runme()
{
Console.WriteLine("runme called");
}

public static void Main()
{
ThreadTest b = new ThreadTest();
Thread t = new Thread(new ThreadStart(b.runme));
t.Start();
}
}
输出
runme called
示例 2
下例使用线程和 lock。只要 lock 语句存在,语句块就是临界区并且 balance 永远不会是负数。
// statements_lock2.cs
using System;
using System.Threading;

class Account
{
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 (this)
{
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
{
public 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();
}
}
}

我们先来看几个案例,看看lock是什么.
1publicclassThreadTest
2{
3privateinti=0;
4publicvoidTest()
5{
6Threadt1=newThread(Thread1);
7Threadt2=newThread(Thread2);
8t1.Start();
9t2.Start();
10}
11publicvoidThread1()
12{
13lock(this)
14{
15Console.WriteLine(this.i);
16Thread.Sleep(1000);
17Console.WriteLine(this.i);
18}
19}
20publicvoidThread2()
21{
22Thread.Sleep(500);
23this.i=1;
24Console.WriteLine("Changethevalueinlocking");
25}
26}
27publicclassThreadTest2
28{
29privateinti=0;
30publicvoidTest()
31{
32Threadt1=newThread(Thread1);
33Threadt2=newThread(Thread2);
34t1.Start();
35t2.Start();
36}
37publicvoidThread1()
38{
39lock(this)
40{
41Console.WriteLine(this.i);
42Thread.Sleep(1000);
43Console.WriteLine(this.i);
44}
45}
46publicvoidThread2()
47{
48lock(this)
49{
50Thread.Sleep(500);
51this.i=1;
52Console.WriteLine("Can'tchangethevalueinlocking");
53}
54}
55}

两段程序有什么区别吗?看看吧,ThreadTest2.Thread2()中多了一个lock(this)却产生了不同的结果

本想在案例一中lock住this对象,让其他的线程不能操作,可是事情不是像我们想象的那样lock(this)是lock this的意思.this中的属性依然能够被别的线程改变.那我们lock住的是什么?是代码段,是lock后面大括号中代码段,这段代码让多个人执行不不被允许的.那返回头来在看lock(this),this是什么意思呢?可以说this知识这段代码域的标志,看看案例二中Thread2.Thread2就明白了,Thread2中的lock需要等到Thread1种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)将索引变为负数。

如果明白了Monitor.Enter的原理,lock当然不再话下.当然lock后括号里面的值不是说把整个对象锁住,而是对他的一个值进行了修改,使别的lock不能锁住他,这才是lock(object)的真面目.

但在实际使用中Monitor还是不推荐,还是lock好的,Monitor需要加上很多try catch才能保证安全性,但lock却帮我们做了,而且lock看起来更优雅.

在静态方法中如何使用lock呢,由于我们没有this可用,所以我们使用typeof(this)好了,Type也有相应的方法地址和索引,所以他也是可以来当作lock的标志的.

但微软不提倡是用public的object或者typeof()或者字符串这样的标志就是因为,如果你的public object在其他的线程中被null并被垃圾收集了,将发生不可预期的错误.

分享到:
评论

相关推荐

    .NET LOCK使用方法

    .NET LOCK使用方法 网上收集,版权为原作者所有,谢谢

    lockfree c#.net

    lockfree JmBucknall.Structures

    DistributedLock:用于分布式同步的.NET库

    分布式锁DistributedLock是一个.NET库,它基于各种基础技术提供了健壮且易于使用的分布式互斥锁,读写器锁和信号灯。 使用DistributedLock,跨多个应用程序/机器同步对代码区域的访问非常简单: using ( await ...

    ASP.NET_Core_in_Action[Andrew_Lock].pdf

    ASP.NET CORE零基础教程,作者大牛。 Summary ASP.NET Core in Action is for C# developers without any web development experience who want to get started and productive fast using ASP.NET Core 2.0 to ...

    6种多线程比较(VB.net版)

    6种多线程速度的比较,曾找了一个C#(感谢原作者),但是本人是vb的爱好者,在csdn上留个备份。(这年头没有币不好混啊)

    asp.net 锁定gridview首行、前几列

    附详细使用说明,非常简单,解决问题直接了当。

    ASP.NET教学讲义,完整章节

    3.3 ASP.NET中的HTML服务器控件 46 3.4 ASP.NET2.0新增控件 54 3.5 客户端处理 61 3.6验证控件 63 3.7自定义验证控件 71 3.8验证总结控件 73 第四章:ASP.NET内置对象 76 4.1内置对象概述 76 4.2 Response对象和...

    .Net 多线程详解

    • .Net线程池有什么不足? 同步 • CLR怎样实现lock(obj)锁定? • WaitHandle是什么,他和他的派生类怎么使用 • 什么是用双锁实现Singleton,为什么要这样做,为什么有人说双锁检验是不安全的 • 互斥对象(Mutex...

    dblock.zip

    dblock.zip

    Stoned Bootkit v2源代码

    Stoned Bootkit v2源代码 附送Antivirus Tracker complete 从官网上下载的就是这个zip了,原汁原味. 官网http://www.stoned-vienna.com/不知道为什么上不了了.这里算是个存档吧 一个分,大家懂的..

    ASP.NET Core in Action

    ASP.NET Core in Action Andrew Lock June 2018 ISBN 9781617294617 712 pages printed in black & white

    asp.net教学讲义

    3.3 ASP.NET中的HTML服务器控件 38 3.3.1 HtmlForm控件 38 3.3.2 HtmlImage控件 40 3.3.3 InputFile控件 42 3.3.4 HtmlGenericControl 控件 43 3.4 ASP.NET2.0新增控件 45 3.4.1 ImageMap控件 45 3.4.2 FileUpload...

    基于.NET串口类

    基于.NET串口类, 内置4个event。 有lock功能。

    freelockqueue(多线程不需要加锁的队列性能很高)

    在多线程情况下,C#的队列入队和出队时需要现场同步,但这样会损失性能,此开源队列可以不需要同步,就能实现多线程操作,极大的提高了程序的运行效率

    .net 分布式锁

    包括redis锁和zookeeper锁的.net实现。 分布式锁在解决分布式环境下的业务一致性是非常有用的。 开源地址:http://git.oschina.net/chejiangyi/XXF.BaseService.DistributedLock

    ASP.NET初学者练习

    注意: 只有在 Web config 文件中的 sessionstate 模式设置为 InProc 时 才会引发 Session End 事件 如果会话模式 设置为 StateServer 或 SQLServer 则不会引发该事件 Application Lock ; Application[&quot;...

    ASP.NET中Application全局对象用法实例浅析

    本文实例讲述了ASP.NET中Application全局对象用法。分享给大家供大家参考。具体如下: Application是应用全局对象,被全体共享。无论通过哪个页面操作Application,另一个页面都可以读取Application信息。 由于...

    解决git:fatal:Unable to create”…/.git/index.lock” 的错误

    报错大致意思就是创建index.lock文件失败,因为已经存在index.lock文件了. index.lock文件是在.git下面, 而.git是一般是隐藏的, 那么可以通过以下命令删除即可. rm -rf /Users/dianji/project/ccpay.h5/.git/index....

Global site tag (gtag.js) - Google Analytics