cam*_*ase 12 c# multithreading
我可以使用Interlocked.*同步方法来更新DateTime变量吗?
我希望在内存中保留最后触摸时间戳.多个http线程将更新最后一次触摸DateTime变量.
我很欣赏DateTime变量是被替换而不是更新的值类型.
我能想到的最好的方法是将时间戳保持为长整数
class x
{
long _lastHit;
void Touch()
{
Interlocked.Exchange( ref _lastHit, DateTime.Now.Ticks );
}
}
Run Code Online (Sandbox Code Playgroud)
选项1:使用long
with Interlocked
和DateTime.ToBinary()
.这不需要volatile
(事实上,如果你有它,你会收到警告)因为Interlocked已经确保了原子更新.您可以通过这种方式获得DateTime的确切值.
long _lastHit;
void Touch()
{
Interlocked.Exchange(ref _lastHit, DateTime.Now.ToBinary());
}
Run Code Online (Sandbox Code Playgroud)
要原子地阅读:
DateTime GetLastHit()
{
long lastHit = Interlocked.CompareExchange(ref _lastHit, 0, 0);
return DateTime.FromBinary(lastHit);
}
Run Code Online (Sandbox Code Playgroud)
这将返回_lastHit的值,如果为0则将其与0交换(即除了原子读取值之外什么都不做).
简单地读取并不好 - 至少因为变量没有标记为易失性,所以后续读取可能只是重用缓存的值.将volatile和Interlocked组合在一起可能会起作用(我不完全确定,但我认为即使另一个内核执行非互锁读取,也不能在不一致的状态下看到互锁写入).但是,如果你这样做,你会得到警告和代码气味,结合两种不同的技术.
选项2:使用锁.在这种情况下不太理想,因为在这种情况下,联锁方法更具性能.但是你可以存储正确的类型,并且它更清晰:
DateTime _lastHit;
object _lock = new object();
void Touch()
{
lock (_lock)
_lastHit = DateTime.Now;
}
Run Code Online (Sandbox Code Playgroud)
你必须使用锁来读取这个值!顺便提一下,除了互斥之外,锁还确保不能看到缓存的值,并且不能重新排序读/写.
非选项:无论是否标记,都不执行任何操作(只需写入值)volatile
.这是错误的 - 即使您从未读过该值,您在32位计算机上的写入可能会以如此不幸的方式交错,从而导致损坏的值:
Thread1: writes dword 1 of value 1
Thread2: writes dword 1 of value 2
Thread2: writes dword 2 of value 2
Thread1: writes dword 2 of value 1
Result: dword 1 is for value 2, while dword 2 is for value 1
Run Code Online (Sandbox Code Playgroud)
是的,你可以这样做。您最大的问题可能是 DateTime.Ticks 的分辨率只有 ~20 毫秒。DateTime last
所以保留 a或 a变量并不重要long ticks
。但由于 Exchange for DateTime 没有过载,因此您需要使用long
.
归档时间: |
|
查看次数: |
9228 次 |
最近记录: |