volatile DateTime

时间:2011-01-28 16:13:07

标签: c# .net multithreading synchronization volatile

由于DateTime不能声明为volatile,这是正确的吗?:

        private DateTime _time;
        public DateTime Time
        {
            get
            {
                Thread.MemoryBarrier();
                return _time;
            }
            set
            {
                _time = value;
                Thread.MemoryBarrier();
            }
        }

可以从不同的线程访问该属性,因此我想确保它们始终获得最新版本,而不使用争用(锁定)。

编辑:

  • 我有一组难以创建的项目,每个项目都有一个名为CreationTime的DateTime属性,指示何时创建此项目。它被初始化为DateTime.UtcNow。
  • 每次访问某个项目时,该属性都会更新为DateTime.UtcNow。
  • 有一个线程,在线程计时器中及时执行,检查是否(DateTime.UtcNow + 1小时)> item.CreationTime,如果为true,则删除该项目。

我想确保当“删除线程”进入集合时,所有项目都有最新的“最后访问”DateTime,因此我可以避免再次创建项目,因为缓存保存了一个值几毫秒:D

提前致谢。

3 个答案:

答案 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)

这是不可能的 - 您需要使用lockMonitor类来同步对该字段的访问。

这是因为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.ExchangeDateTime的刻度一起使用,因为它可以原子地存储Int64。

但是如果你切换到滴答,你需要知道只有62位用于刻度,2位用于那种。所以你不要失去那种。

即使你让getter和setter原子线程安全,我也不确定这是否足够。因为时间可以在你的吸气剂返回的时间和你实际工作的时间之间变化。所以你的时间总是过时的。