通过前边对Interlocked类的学习,敬佩内行对线程同步机制有了更深的明白,今天咱们将连续需要另一种同步机制——锁lock。
lock是C#言语中的重要字,是线程同步机制的一种浅易的互斥锁结束神志,它不错保证在并吞手艺唯唯一个线程能够拜访被锁定的代码块。其责任旨趣也很浅易,即是通过lock创建一个互斥锁,当一个线程获得到此互斥锁则此线程不错参预被lock保护的代码块,同期其他线程将被险峻无法参预此代码块,直至第一个线程开释此互斥锁,其他线程才不错获得此互斥锁并参预代码块。
lock的使用也杰出浅易,语法如下:
lock (obj)
{
//线程不安全的代码块
}
天然lock使用起来浅易便捷,然则使用神志不正确也很容易产生各式奇奇怪怪的问题。
01、幸免锁定this
这种使用神志会导致两个问题:
1.不成控性:lock(this)锁定的限度是总共这个词实例,这也就意味着其他线程不错通过该实例中的其他设施拜访该锁,进而酿成一个实例中多个使用lock(this)的设施之前彼此影响。
2.外部可见性:this示意现时实例的援用,它是群众的,因此外部代码也不错拜访,这也就意味着外部代码不错通过lock(实例)拜访lock(this)锁,从而使同步机制失去罢休。
底下咱们胜利看代码:
咱们望望代码实际成果:
这里例子不错很好的阐发lock(this)代理的问题,本来不错三个线程并发实际的三段代码,因为使用了并吞个锁,导致三个线程只可轨则实际。其中Method1和Method2体现了并吞实例内设施彼此影响,Method3和Method1、Method2体现了因为交流实例导致实例里面设施和实例外部设施彼此影响。
02、幸免锁定群众对象
这种使用神志会导致两个问题:
1.全局影响:群众对象,罕见是 public static 对象,很大要率会被多个类,以致多个模块援用,因此锁定群众对象很可能导致全局限度内的同步,大大增多了死锁、竞争条目的产生的风险。
2.不成瞻望性:因为群众对象对全局可拜访,因此如果其他模块锁定此群众对象,则当出现问题时将难以摈斥调试问题。
看底下代码:
在望望实际成果:
不错发现因为锁定了并吞个群众对象,迪士尼彩乐园官网人类导致两个不同线程的不同实例,也曾产生彼此争抢锁的问题。
03、幸免锁定字符串
在西晋灭亡后的那个时代,整个北方就像一个超级大战场,政权像走马灯似的换来换去,民族之间矛盾重重,打得那叫一个昏天黑地。汉人贵族们都没了安稳日子,到处流浪,少数民族也都不甘示弱,到处抢地盘。就在这么个乱得像一锅粥的“五胡十六国”时期,居然有四颗超耀眼的将星要升起啦!他们是谁?又怎么能在这乱世里折腾出名堂呢?这免不了让人好奇。
在C#中,字符串因其不成变性和字符串池的原因,在总共这个词设施中一个字符串一朝创建就不会鼎新,如果对其修改则产生新的字符串对象,而原字符串对象保握不变;同期如果创建两个交流本色的字符串,则它们分享并吞个内存地址。
这就导致锁定字符串极其危急尤其危急,因为总共这个词设施中任何给定字符串皆唯唯一个实例,而在总共这个词设施中唯独锁定交流本色的字符串皆会酿成竞争条目。
咱们望望实际成果:
不错发现天然在两个类平差别使用了两个字符串“abc”,但关于总共这个词设施来说它们皆指向了并吞个实例,因此共用了一把锁。
04、提神锁定非readonly对象
这是因为如果锁对象为非只读对象,就可能发生某个lock代码块中修改锁对象,从而导致
锁对象变更,进而使得其他线程不错流畅无阻的参预该代码块。
如下示例:
再来看实际成果:
不错发现三个线程果真同期参预,lock根底就莫得起到锁的作用。
05、提神锁定静态对象
关于是否需要锁定静态对象取决于你的需求。
1.如果要在静态设施中使用lock时,则锁定的对象也必须如若静态对象。
2.如果但愿类的每个实例皆有独处的锁对象,则锁定非静态对象。
3.如果但愿类的总共实例分享并吞个锁,则锁定静态对象。
代码示举例下:
这是因为静态字段是总共实例分享的,其内存地址在总共这个词设施的生命周期内是唯一的迪士尼彩乐园,总共实例拜访并吞个内存地址,因此锁定静态对象时要罕见提神。
下一篇:没有了