【发布时间】:2015-12-21 11:38:50
【问题描述】:
如标题所述,我有这种情况
lock ( _myLockObj )
{
// protected section here ( select + update over SQL Tables)
}
这很好用,但有时我不需要线程安全,因为数据保证不会发生任何错误(即使两个线程并行运行)但我需要速度。 目前程序可以理解线程何时可能存在线程安全问题,何时不存在(什么时候我需要尽可能快)。
我要实现的是该锁定指令的可选性,因此只有在适当的条件为真时它才会生效。
例如:
lock ( _myLockObj ) && flag
我很确定 lock 关键字不提供这种语义,我会理解实现该行为的正确方法是什么。
【问题讨论】:
-
当你说你不需要线程安全时,你的意思是你知道锁对象不可能被锁定吗?或者你的意思是它可以被锁定但你仍然不需要获取它? (如果是后者,为什么不通过更细粒度的锁来解决呢?)
-
我的方法是完全线程安全的,所以一般我不需要锁。不是线程安全的是使用 linq 进行的表操作,因为数据库是跨每个线程的共享资源。可能会发生两个线程尝试对同一数据进行两次不同的操作,这是一个问题。这种情况很少见,我可以理解它什么时候可能发生,什么时候肯定不能(大多数数据只需要插入,并且保证是一次插入)。当我确定它不会发生时,我会避免锁定指令(以获得速度)
-
@Skary 使用数据库事务处理它可能会更好,而不是线程同步。
-
@Jakub 我害怕分布式事务(我需要启用它才能以这种方式进行)。不仅如此,过去我使用事务作为解决方案(特别是使用 linq Select + Update)有奇怪的行为。我对过去的问题的原因没有很好的看法,但最后我决定避免交易,我尽可能多地使用这种方法。
-
select+insert的问题是它在获得共享锁后会尝试获得排他锁。根据事务隔离级别,这将导致在select之后立即释放共享锁(并允许 T1:Select - T2:Select - T2:Update - T1:Update 序列),或者如果锁被保留则死锁。您需要先获得一个独占锁才能使其正常工作(您应该能够找到一些方法来在 SO 上执行此操作)。线程同步的一个问题是它只能在一个进程(或机器,如果你使用像命名互斥锁之类的东西)内工作
标签: c# multithreading locking