问梦幻西游有个**的力地府和一个50级的大唐,想具体玩一个号,玩哪个好,都是平民号。
-
Mr.Zhang
一、lock定义
lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断。它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待。这是通过在代码块运行期间为给定对象获取互斥锁来实现的。在多线程中,每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数。这可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生。而在.net中最好了解一下进程、应用域和线程的概念,因为lock是针对线程一级的,而在.net中应用域是否会对lock起隔离作用,我的猜想是,即不在同一应用域中的线程无法通过lock来中断;另外也最好能了解一下数据段、代码段、堆、栈等概念。在c# lock关键字定义如下:
lock(expression)statement_block,其中expression代表你希望跟踪的对象,通常是对象引用。如果你想保护一个类的实例,一般地,你可以使用th**;如果你想保护一个静态变量(如互斥代码段在一个静态方法内部),一般使用类名就可以了。而statement_block就是互斥段的代码,这段代码在一个时刻内只可能被一个线程执行。二、简单解释一下执行过程
先来看看执行过程,代码示例如下:
private static object o**=new object();lock(obj)
{
锁定运行的代码段
} 假设线程a先执行,线程b稍微慢一点。线程a执行到lock语句,判断obj是否已申请了互斥锁,判断依据是逐个与已存在的锁进行object.referenceequals比较(此处未加证实),如果不存在,则申请一个新的互斥锁,这时线程a进入lock里面了。这时假设线程b启动了,而线程a还未执行完lock里面的代码。线程b执行到lock语句,检查到obj已经申请了互斥锁,于是等待;直到线程a执行完毕,释放互斥锁,线程b才能申请新的互斥锁并执行lock里面的代码。三、lock的对象选择问题
接下来说一些lock应该锁定什么对象。1、为什么不能lock值类型
比如lock(1)呢?lock本质上monitor.enter,monitor.enter会使值类型装箱,每次lock的是装箱后的对象。lock其实是类似编译器的语法糖,因此编译器直接限制住不能lock值类型。退一万步说,就算能编译器允许你lock(1),但是object.referenceequals(1,1)始终返回false(因为每次装箱后都是不同对象),也就是说每次都会判断成未申请互斥锁,这样在同一时间,别的线程照样能够访问里面的代码,达不到同步的效果。同理lock((object)1)也不行。2、lock字符串
那么lock("xxx")字符串呢?msdn上的原话是:
锁定字符串尤其危险,因为字符串被公共语言运行库(clr)“暂留”。这意味着整个程序中任何给定字符串都只有一个实例,就是这同一个对象表示了所有运行的应用程序域的所有线程中的该文本。因此,只要在应用程序进程中的任何位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。3、msdn推荐的lock对象
通常,最好避免锁定 public 类型或锁定不受应用程序控制的对象实例。例如,如果该实例可以被公开访问,则 lock(th**)可能会有问题,因为不受控制的代码也可能会锁定该对象。这可能导致死锁,即两个或更多个线程等待释放同一对象。出于同样的原因,锁定公共数据类型(相比于对象)也可能导致问题。而且lock(th**)只对当前对象有效,如果多个对象之间就达不到同步的效果。而自定义类推荐用私有的只读静态对象,比如:
private static readonly object obj=new object();为什么要设置成只读的呢?这时因为如果在lock代码段中改变obj的值,其它线程就畅通无阻了,因为互斥锁的对象变了,object.referenceequals必然返回false。4、lock(typeof(class))
与锁定字符串一样,范围太广了。五、特殊问题:lock(th**)等的详细解释
在以前编程中遇到lock问题总是使用lock(th**)一锁了之,出问题后翻看msdn突然发现下面几行字:通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock(th**)、lock(typeof(mytype))和 lock("mylock")违反此准则:如果实例可以被公共访问,将出现c# lock th**问题。如果 mytype 可以被公共访问,将出现 lock(typeof(mytype))问题。由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“mylock”)问题。来看看c# lock th**问题:如果有一个类class1,该类有一个方法用lock(th**)来实现互斥:
publicvoidmethod2()
{
lock(th**)
{
system.windows.forms.**box.show("method2end");}
}
如果在同一个class1的实例中,该method2能够互斥的执行。但是如果是2个class1的实例分别来执行method2,是没有互斥效果的。因为这里的lock,只是对当前的实例对象进行了加锁。lock(typeof(mytype))锁定住的对象范围更为广泛,由于一个类的所有实例都只有一个类型对象(该对象是typeof的返回结果),锁定它,就锁定了该对象的所有实例,微软现在建议,不要使用lock(typeof(mytype)),因为锁定类型对象是个很缓慢的过程,并且类中的其他线程、甚至在同一个应用程序域中运行的其他程序都可以访问该类型对象,因此,它们就有可能代替您锁定类型对象,完全阻止您的执行,从而导致你自己的代码的挂起。锁住一个字符串更为神奇,只要字符串内容相同,就能引起程序挂起。原因是在.net中,字符串会被暂时存放,如果两个变量的字符串内容相同的话,.net会把暂存的字符串对象分配给该变量。所以如果有两个地方都在使用lock(“my lock”)的话,它们实际锁住的是同一个对象。到此,微软给出了个lock的建议用法:锁定一个私有的static 成员变量。net在一些集合类中(比如arrayl**t,hashtable,queue,stack)已经提供了一个供lock使用的对象syncroot,用reflector工具查看了syncroot属性的代码,在array中,该属性只有一句话:return th**,这样和lock array的当前实例是一样的。arrayl**t中的syncroot有所不同
get
{
if(th**._syncroot=**)
{
interlocked.compareexchange(refth**._syncroot,newobject(),**);}
returnth**._syncroot;其中interlocked类是专门为多个线程共享的变量提供原子操作(如果你想锁定的对象是基本数据类型,那么请使用这个类),compareexchange方法将当前syncroot和**做比较,如果相等,就替换成new object(),这样做是为了保证多个线程在使用syncroot时是线程安全的。集合类中还有一个方法是和同步相关的:synchronized,该方法返回一个对应的集合类的wrapper类,该类是线程安全的,因为他的大部分方法都用lock来进行了同步处理,比如add方法:
publicoverridevoidadd(objectkey,objectvalue)
{
lock(th**._table.syncroot)
{
th**._table.add(key,value);}
}
这里要特别注意的是msdn提到:从头到尾对一个集合进行枚举本质上并不是一个线程安全的过程。即使一个集合已进行同步,其他线程仍可以修改该集合,这将导致枚举数引发异常。若要在枚举过程中保证线程安全,可以在整个枚举过程中锁定集合:
queuemycollection=newqueue();lock(mycollection.syncroot){
foreach(objectiteminmycollection){
insertyourcodehere.
}
}
最后
注意:应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock(th**)、lock(typeof(mytype))和 lock("mylock")违反此准则:
1)如果实例可以被公共访问,将出现 lock(th**)问题;2)如果 mytype 可以被公共访问,将出现 lock(typeof(mytype))问题;3)由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock("mylock")问题;最佳做法是定义 private 对象来锁定,或 private static 对象变量来保护所有实例所共有的数据。
-
问 梦幻西游**力地府装备上什么符石最好一个个说下
提问时间:2024-05-04 11:51:31
答 带溅射的组合.+防御的组合.+灵力组合.+伤害的组合.如果是jy的武器.可以打个+门派技能的符石.手打.希望采纳.
-
问 谁能给我一个梦想海贼王的号,还有具体的哪个服 谢谢
提问时间:2024-05-04 16:19:22
答 出售梦想海贼王账号 船员等级:40 人物8a 有三大将 艾尼路 老沙 装备全a 人物平均等级120级 总身价:263000
-
问 我有一个大号和一个小号,请问怎样才能把大号的东西给小号
提问时间:2024-05-04 21:24:08
答 呃~新玩的吧?我一开始也不知道怎么**,呵呵。现在告诉你哦~**后就可以组队。东西少的话可以左键点要交给的东西,然后再点左侧要给的队友的头像就行了;东西多的话就...
-
问 梦幻西游5力五庄和5力大唐哪个好一些?需要详细
提问时间:2024-05-04 19:21:56
答 感觉wz好点,.五力有输出,还能封.能回血回蓝.不用带破血.大唐只有三刀,5力加点又没血又没防御,三刀输出是有了,完了就站着等死
-
问 梦幻西游109魔王和大唐哪个好玩
提问时间:2024-05-04 20:34:24
答 果断玩魔王啊,109法系很**的。玩起来很爽的,而且109常规活动,任务,大唐几本没人要,都要秒系的,固定队伍除外,法系很吃香的。论花费的话个人感觉差不多。魔王...
-
问 梦幻西游同一个账号怎样把一个角色的钱和物品转到该号的另一个角色上
提问时间:2024-05-04 05:45:21
答 同一个号上的不同id只有自己开小号转了,不然你就把号上的id上cbg卖给自己建的其他号上好了。创号不需要邮箱的啊。你不一定非要有这个邮箱。只要自己用个*@163...
-
问 梦幻西游手游,打算先停**,最终停89级!我朋友一个玩方寸,一个玩大唐,我们三个都是平民**,我玩
提问时间:2024-05-04 20:18:48
答 大唐门派特色:装备耐久度的消耗速度为普通的1/2。可用技能:横扫千军/后发制人/破釜沉舟/杀气决/安神决/反间之计/兵器。属性分配:力量为主、体耐敏均衡。推荐特...
-
问 梦幻西游我打算弄一个全50队伍..4pt1wz还是**t2wz好?都是做任务的号(难度大的任务),选那个组合好?
提问时间:2024-05-04 23:52:30
答 这个就需要看你做什么任务了 50的队伍是在想不出有那些难度大的 副本?还是其他 我不要确定 凭以往经验给点个人建议你你的配置不管做什么任务 在低级别都是以耗为主...
-
问 大唐游仙记和梦幻西游哪个好玩 大唐游仙记与梦幻西游
提问时间:2024-05-04 14:11:40
答 大唐游仙记和梦幻西游的玩法相似,只是内容少一些。游仙记现在好像基本已经黄了,没几个人玩了,想热闹还是玩梦幻吧。