由于DateTime
不能声明为volatile,这是正确的吗?:
private DateTime _time;
public DateTime Time
{
get
{
Thread.MemoryBarrier();
return _time;
}
set
{
_time = value;
Thread.MemoryBarrier();
}
}
可以从不同的线程访问该属性,因此我想确保它们始终获得最新版本,而不使用争用(锁定)。
编辑:
我想确保当“删除线程”进入集合时,所有项目都有最新的“最后访问”DateTime,因此我可以避免再次创建项目,因为缓存保存了一个值几毫秒:D
提前致谢。
答案 0 :(得分:13)
正。
但是,你有另一种选择。将时间存储为Int64滴答计数,并使用InterlockedExchange
进行设置。然后,线程可以使用Int64构造函数构造自己的DateTime
,不会产生争用,也不会产生锁定。
编辑:
鉴于您提供了更多信息,现在提供示例更容易。
public class Cache
{
class CacheEntry
{
private Int64 m_Touched;
public CacheEntry()
{
Touch();
}
public void Touch()
{
System.Threading.Interlocked.Exchange(ref m_Touched, DateTime.Now.Ticks);
}
public DateTime Touched
{
get
{
return new DateTime(Interlocked.Read(ref m_Touched));
}
}
} // eo class CacheEntry
} // eo class Cache
答案 1 :(得分:2)
这是不可能的 - 您需要使用lock
或Monitor
类来同步对该字段的访问。
这是因为DateTime
是一种值类型 - 结构。
来自MSDN - volatile (C# Reference):
volatile关键字可以应用于以下类型的字段:
- 参考类型。
- 指针类型(在不安全的上下文中)。请注意,虽然指针本身可以是易失性的,但它指向的对象却不能。换句话说,你不能声明一个“指向易失性的指针。”
- 类型,例如sbyte,byte,short,ushort,int,uint,char,float和bool。
- 具有以下基本类型之一的枚举类型:byte,sbyte,short,ushort,int或uint。
- 已知为参考类型的通用类型参数。
- IntPtr和UIntPtr。
正如其他人所提到的,您可以使用Ticks
来跟踪时间。
答案 2 :(得分:2)
您的代码不是线程安全的,因为DateTime
的赋值不保证是原子的。通常,高达32位的整数赋值是原子的,但64不一定是原子的。
您可以将Interlocked.Exchange
与DateTime
的刻度一起使用,因为它可以原子地存储Int64。
但是如果你切换到滴答,你需要知道只有62位用于刻度,2位用于那种。所以你不要失去那种。
即使你让getter和setter原子线程安全,我也不确定这是否足够。因为时间可以在你的吸气剂返回的时间和你实际工作的时间之间变化。所以你的时间总是过时的。