изменчивый DateTime - PullRequest
       34

изменчивый DateTime

10 голосов
/ 28 января 2011

Поскольку DateTime не может быть объявлено как volatile, не так ли?:

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

К этому свойству можно обращаться из разных потоков, поэтому я хочу убедиться, что они всегда получают последнюю версию без использованияcontention (lock).

EDIT:

  • У меня есть коллекция сложных для создания элементов, каждый из которых имеет свойство DateTime с именем CreationTime, указывающее, когда этот элемент был создан.Он инициализируется в DateTime.UtcNow.
  • Каждый раз, когда к элементу осуществляется доступ, это свойство обновляется до DateTime.UtcNow.
  • Существует поток, который выполняется своевременно в поточном таймере, которыйпроверяет, если (DateTime.UtcNow + 1 час)> item.CreationTime, если true, удаляет элемент.

Я хочу убедиться, что, когда «поток удаления» входит в коллекцию, все элементыу них есть последний DateTime последнего доступа, поэтому я могу избежать повторного создания элемента только потому, что в кеше хранится значение в течение пары миллисекунд: D

Заранее спасибо.

Ответы [ 3 ]

13 голосов
/ 28 января 2011

Точно.

Но у вас есть другой вариант. Сохраните время как счетчик тиков Int64 и используйте InterlockedExchange для установки. Затем потоки могут создавать свои собственные DateTime, используя конструктор Int64 , что не вызывает никаких конфликтов и блокировок.

EDIT:

Учитывая, что вы предоставили больше информации, теперь проще привести пример.

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
2 голосов
/ 28 января 2011

Ваш код не является потокобезопасным, поскольку присвоение DateTime не гарантированно является атомарным.В общем случае целые числа до 32 битов являются атомарными, но 64 не обязательно должны быть атомарными.

Вы, вероятно, можете использовать Interlocked.Exchange с галочками DateTime, поскольку это может атомарно хранить Int64.

Но если вы переключаетесь на тики, вы должны знать, что только 62 бита используются для тиков, и 2 бита для вида.Таким образом, вы не потеряете вид.

И даже если вы сделаете метод получения и установки атомарным потокобезопасным, я не уверен, достаточно ли этого.Поскольку время может меняться между временем возвращения вашего геттера и временем, которое вы фактически работаете с временем, которое у вас есть.Так что ваше время всегда может быть устаревшим.

2 голосов
/ 28 января 2011

Это невозможно - вам нужно будет использовать lock или класс Monitor для синхронизации доступа к полю.

Это потому, что DateTime - это тип значения - структура.

Из MSDN - энергозависимый (C # Reference) :

Ключевое слово volatile можно применять к полям следующих типов:

  • Типы ссылок.
  • Типы указателей (в небезопасном контексте). Обратите внимание, что, хотя сам указатель может быть изменчивым, объект, на который он указывает, не может. Другими словами, вы не можете объявить «указатель на volatile».
  • Типы, такие как sbyte, byte, short, ushort, int, uint, char, float и bool.
  • Тип enum с одним из следующих базовых типов: byte, sbyte, short, ushort, int или uint.
  • Параметры общего типа, известные как ссылочные типы.
  • IntPtr и UIntPtr.

Как уже упоминалось, вы можете использовать Ticks для отслеживания времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...