irr*_*iss 4 .net c# multithreading volatile concurrentdictionary
我想用网络智慧澄清一些关于.net中多线程的时刻.互联网上有很多关于它的东西但是我无法找到我的问题的好答案.
假设我们希望在同类线程中保持安全状态.简单的情况是当state为int时:
class Class1
{
volatile int state = 0;
public int State
{
get
{
return state;
}
}
public Action<int> StateUpdated;
public void UpdateState(int newState)
{
state = newState;
if (StateUpdated != null)
StateUpdated(newState);
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,'volatile'应该足够了.无论什么线程需要获取当前状态,它都可以使用永远不会被缓存的"State"属性.无论线程想要更新状态,它都可以使用"UpdateState"安全地进行更新.
但是,如果州是一个结构,该怎么办?完全'锁定'是唯一的方法吗?附带问题:变量是否仍然可以缓存在锁内?
struct StateData
{
//some fields
}
class Class1
{
StateData state;
public StateData State
{
get
{
return state;
}
}
public Action<StateData> StateUpdated;
public void UpdateState(StateData newState)
{
state = newState;
if (StateUpdated != null)
StateUpdated(newState);
}
}
Run Code Online (Sandbox Code Playgroud)
最后的主要问题是:此代码是否足以在多线程环境中管理状态对象的集合?或者可能存在一些隐藏的问题.
public struct StateData
{
//some fields
}
public delegate void StateChangedHandler(StateData oldState, StateData newState);
class Class1
{
ConcurrentDictionary<string, StateData> stateCollection = new ConcurrentDictionary<string, StateData>();
public StateData? GetState(string key)
{
StateData o;
if (stateCollection.TryGetValue(key, out o))
return o;
else
return null;
}
public StateChangedHandler StateUpdated;
void UpdateState(string key, StateData o)
{
StateData? prev = null;
stateCollection.AddOrUpdate(key, o,
(id, old) =>
{
prev = old;
return o;
}
);
if (prev != null && StateUpdated != null)
StateUpdated(prev.Value, o);
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢你的回答.
但是,如果州是一个结构,该怎么办?完全'锁定'是唯一的方法吗?
该volatile关键字仅适用于可以原子更新的类型,例如引用类型变量,指针和基元类型.
但是,请注意,volatile除了访问标记变量之外,还提供了一些保证.特别是,在写入带volatile标记的存储器位置之前发生的所有对存储器的写入都将在从相同volatile标记的存储器位置读取之后从存储器读取的任何代码中看到.
从理论上讲,这意味着您可以使用volatile字段为其他内存位置提供类似易失性的行为.
但实际上,仍然存在一个问题:对相同内存位置的新写入可能会也可能不会显示,当然并非所有写入都可以原子方式完成.因此,这种使用volatile实际上只适用于可能被标记为易失性的其他内存位置,即使这样也不能确保您不会获得比标记的内存位置更新的值volatile.
这是一个很长的说法,你应该使用lock并完成它.:)
附带问题:变量是否仍然可以缓存在锁内?
我不完全确定你的意思是什么.但总的来说:只要这些优化不会影响单个线程中代码的观察行为,就允许编译器进行优化.如果您考虑的缓存类型不违反此规则,则可能允许.否则就不会.
这段代码是否足以在多线程环境中管理状态对象的集合?
发布的代码似乎很好,至少就确保字典始终提供连贯的状态值而言.
| 归档时间: |
|
| 查看次数: |
730 次 |
| 最近记录: |