易失性日期时间

发布于 2024-10-14 19:12:15 字数 772 浏览 2 评论 0原文

由于DateTime不能声明为易失性,这是对的吗?

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

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

编辑:

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

我想确保当“删除线程”进入集合时,所有项目都有其最新的“上次访问”DateTime,这样我就可以避免仅仅因为缓存保留而再次创建该项目几毫秒的值。 :D

As DateTime cannot be declared as volatile, is this right?

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

That property could be accessed from different threads, so I want to ensure they get always the latest version, without use contention (lock).

EDIT:

  • I have a collection of hard-to-create items, each one has a DateTime property named CreationTime, indicating when this item was created. It's initialized to DateTime.UtcNow.
  • Every time a item is accessed, that property is updated to DateTime.UtcNow.
  • There is a thread, that executes in timely fashion in a threaded timer that checks if (DateTime.UtcNow + 1 hour) > item.CreationTime, if true it deletes the item.

I want to ensure that when the "deletion thread" comes into the collection, all the items have their latest "last access" DateTime on it, so I can avoid create the item again just because a cache held the value for a couple of milliseconds. :D

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

腻橙味 2024-10-21 19:12:15

恰恰。

但是,你还有另一种选择。将时间存储为 Int64 刻度计数,并使用 InterlockedExchange 进行设置。然后,线程可以使用 Int64 构造自己的 DateTime a> 构造函数,没有争用,也没有锁。

编辑:

鉴于您提供了更多信息,现在更容易提供示例。

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

Precisely.

But, you have another option. Store the time as an Int64 tick count, and use InterlockedExchange to set. Threads can then construct their own DateTime using The Int64 constructor, giving you no contention and no locks.

EDIT:

Given that you've provided more information, it's easier now to provide an example.

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
萌无敌 2024-10-21 19:12:15

您的代码不是线程安全的,因为 DateTime 的分配不能保证是原子的。一般来说,32 位以下的整数赋值是原子的,但 64 位的整数则不必是原子的。

您可能可以将 Interlocked.Exchange 与 DateTime 的刻度一起使用,因为它可以自动存储 Int64。

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

即使你使 getter 和 setter 原子化并成为线程安全的,我也不确定这是否足够。由于获取器返回的时间和您实际使用所获得的时间之间的时间可能会发生变化。所以你的时间总是会过时。

Your code isn't thread-safe since the assignment of DateTime isn't guaranteed to be atomic. In general assignments of integers up to 32bits are atomic, but 64 needn't be atomic.

You probably can use Interlocked.Exchange with the ticks of the DateTime since that can atomically store an Int64.

But if you switch to ticks you need to know that only 62 bits are used for the ticks, and 2 bits for the kind. So you don't lose the kind.

And even if you make the getter and setter atomic an threadsafe, I'm not sure if that's enough. Since the time can change between the time where your getter returns and the time you actually work with the time you got. So your time can always be outdated.

老街孤人 2024-10-21 19:12:15

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

这是因为 DateTime 是一种值类型 - 一种结构。

来自 MSDN - 易失性(C# 参考)

volatile 关键字可以应用于以下类型的字段:

  • 参考类型。
  • 指针类型(在不安全的上下文中)。请注意,虽然指针本身可以是易失性的,但它指向的对象却不能。换句话说,您不能声明“指向 volatile 的指针”。
  • sbyte、byte、short、ushort、int、uint、char、float 和 bool 等类型。
  • 具有以下基本类型之一的枚举类型:byte、sbyte、short、ushort、int 或 uint。
  • 已知为引用类型的通用类型参数。
  • IntPtr 和 UIntPtr。

正如其他人提到的,您可以使用 Ticks 来跟踪时间。

This is not possible - you will need to use lock or the Monitor class to synchronize access to the field.

This is because DateTime is a value type - a structure.

From MSDN - volatile (C# Reference):

The volatile keyword can be applied to fields of these types:

  • Reference types.
  • Pointer types (in an unsafe context). Note that although the pointer itself can be volatile, the object that it points to cannot. In other words, you cannot declare a "pointer to volatile."
  • Types such as sbyte, byte, short, ushort, int, uint, char, float, and bool.
  • An enum type with one of the following base types: byte, sbyte, short, ushort, int, or uint.
  • Generic type parameters known to be reference types.
  • IntPtr and UIntPtr.

As others have mentioned, you can use Ticks to track time.

时光倒影 2024-10-21 19:12:15

.NET Core 包含 不安全.As 方法,它允许对 DateTime 变量执行易失性读/写,如下所示:

public static DateTime VolatileRead(ref DateTime location)
{
    ref ulong unsafeLocation = ref Unsafe.As<DateTime, ulong>(ref location);
    ulong result = Volatile.Read(ref unsafeLocation);
    return Unsafe.As<ulong, DateTime>(ref result);
}

public static void VolatileWrite(ref DateTime location, DateTime value)
{
    ref ulong unsafeLocation = ref Unsafe.As<DateTime, ulong>(ref location);
    ref ulong unsafeValue = ref Unsafe.As<DateTime, ulong>(ref value);
    Volatile.Write(ref unsafeLocation, unsafeValue);
}

用法:

DateTime latest = VolatileRead(ref _dateTimeField);

VolatileWrite(ref _dateTimeField, newDateTime);

这是一个 hack,因为它取决于 DateTime 类型永远由 ulong 字段支持。根据具体情况,自行判断使用它是否合适/安全/谨慎。

来自 源代码

private readonly ulong _dateData;

The .NET Core includes the Unsafe.As method, which allows to perform a volatile read/write on a DateTime variable like this:

public static DateTime VolatileRead(ref DateTime location)
{
    ref ulong unsafeLocation = ref Unsafe.As<DateTime, ulong>(ref location);
    ulong result = Volatile.Read(ref unsafeLocation);
    return Unsafe.As<ulong, DateTime>(ref result);
}

public static void VolatileWrite(ref DateTime location, DateTime value)
{
    ref ulong unsafeLocation = ref Unsafe.As<DateTime, ulong>(ref location);
    ref ulong unsafeValue = ref Unsafe.As<DateTime, ulong>(ref value);
    Volatile.Write(ref unsafeLocation, unsafeValue);
}

Usage:

DateTime latest = VolatileRead(ref _dateTimeField);

VolatileWrite(ref _dateTimeField, newDateTime);

This is a hack, as it depends on the DateTime type being backed by a ulong field forever. Use your own judgement whether it's appropriate/safe/prudent to use it, in a case-by-case basis.

From the source code of the DateTime struct:

private readonly ulong _dateData;
瑶笙 2024-10-21 19:12:15

这行得通吗?

public class VolatileDateTime
{
    private readonly DateTime _datetime;
    public VolatileDateTime(DateTime datetime)
    {
        _datetime = datetime;
    }

    public DateTime Value { get => _datetime; }
}

……

volatile VolatileDateTime vDateTime = new VolatileDateTime(DateTime.Now)

if (vDateTime.Value > somedatetime)
    dosomething();

Would this work?

public class VolatileDateTime
{
    private readonly DateTime _datetime;
    public VolatileDateTime(DateTime datetime)
    {
        _datetime = datetime;
    }

    public DateTime Value { get => _datetime; }
}

...

volatile VolatileDateTime vDateTime = new VolatileDateTime(DateTime.Now)

...

if (vDateTime.Value > somedatetime)
    dosomething();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文