我想知道在特定情况下是否有这样的情况,我们有bool标志,表明某些服务是否可用:
SELECT * FROM mainTable
LEFT JOIN TblReportDate ON mainTable.id >= TblReportDate.id
在多线程环境中将bool字段设置为volatile是否足够,或者使用锁甚至是Monitor更好。
在这种特定情况下,如果此时服务不可用,则无需等待它再次可用。
答案 0 :(得分:6)
不,这还不够。易失性不足以管理多线程,实际上,volatile可能会增加预期结果与实际结果之间的差距。访问变量(isAvailable)并修改它仍然会导致竞争条件。 您可以使用锁定,信号量或原子操作来管理多线程操作。
private object myLock = new object;
private void foo()
{
lock(myLock)
{
DoSomething();
}
}
或
[MethodImpl(MethodImplOptions.Synchronized)]
private void foo()
{
// DoSomething
}
@Fildor是对的。我想念问题,因此,我编辑了我的答案。下面的代码,如果资源没有被锁定,代码锁定资源并执行某些操作,否则它会跳过关键部分。
private object myLock = new object;
private void foo()
{
if (Monitor.TryEnter(lockObject))
{
try
{
//do something
}
finally
{
Monitor.Exit(lockObject);
}
}
}
答案 1 :(得分:1)
其他答案为您的问题提供了解决方案,但万一您想知道为什么您的解决方案无效......
......这是可能发生的事情:
Thread A Thread B
-------- --------
fetches isAvailable from memory
Tests the fetched value, it's true! fetches isAvailable from memory
sets isAvailable=false Tests the fetched value, it's true!
calls DoSomething() sets isAvailable=false
... calls DoSomething()
...
答案 2 :(得分:-1)
Adem Catamak绝对正确,lock
通常是要走的路。
但是,如果您的代码对性能至关重要,则可以查看使用MemoryBarrier
和volatile
。
此页面在这方面非常有用:http://www.albahari.com/threading/part4.aspx
要在lock
答案中添加一些内容,您可以随时抽象出来(未经测试,但您可以获得要点:
public class ThreadSafeObject
{
private object _myObject; //Must be reference type
public object MyObject
{
get
{
lock (_myObject)
{
return _myObject;
}
}
set
{
lock (_myObject)
{
_myObject = value;
}
}
}
}
您甚至可以使用泛型来实现这一目标:
public class ThreadSafeGeneric<T>
{
private T _myObject;
public T MyObject
{
get
{
lock (_myObject)
{
return _myObject;
}
}
set
{
lock (_myObject)
{
_myObject = value;
}
}
}
}