2011-01-28 3 views
10

DateTimeのような揮発性のDateTime使用競合せずに揮発性として宣言することはできません、この権利は?:ある

 private DateTime _time; 
     public DateTime Time 
     { 
      get 
      { 
       Thread.MemoryBarrier(); 
       return _time; 
      } 
      set 
      { 
       _time = value; 
       Thread.MemoryBarrier(); 
      } 
     } 
プロパティは異なるスレッドからアクセスすることができることを

ので、私は、彼らは常に最新バージョンを取得確保したいです、(ロック)。

EDIT:

  • 私はハード・ツー・作成したアイテムのコレクションを持って、それぞれがこの項目が作成されたかを示す、CREATIONTIMEという名前のDateTimeプロパティを持っています。 DateTime.UtcNowに初期化されます。
  • アイテムにアクセスするたびに、そのプロパティはDateTime.UtcNowに更新されます。
  • (DateTime.UtcNow + 1 hour)> item.CreationTimeをチェックするスレッドタイマーでタイムリーに実行されるスレッドがあります(trueの場合、アイテムを削除します)。

「削除スレッド」がコレクションに入ったとき、すべてのアイテムに最新の「最終アクセス」のDateTimeがあることを確認したいので、キャッシュが数ミリ秒間の値:D

ありがとうございます。

+0

あなたがしようとしていることが意味をなさないかどうかはわかりません。どのように最新のバージョンを定義しますか? – CodesInChaos

+0

投稿を更新しました – vtortola

+1

特定の期間よりも古い未使用のオブジェクトを削除するキャッシュを実装しているとすれば、ここではInterlockedExchangeの解決策があると思います。 –

答えて

12

正確に。

しかし、別の選択肢があります。 Int64ティックカウントとして時間を格納し、InterlockedExchangeを使用して設定します。スレッドは、Int64コンストラクタを使用して独自のDateTimeを構築することができます。これにより、競合が発生せず、ロックも行われません。

EDIT:あなたはより多くの情報を提供してきましたことを考えると

、それは例を提供するために簡単になりました。 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 
+3

生の目盛を保存するのではなく、 'ToBinary' /' FromBinary'を使う方が良いので、 'DateTimeKind'も同様に保存されます。 (私は、OPはたぶん、ロックと過度に巧妙になるようにするのではなく、単純な 'DateTime'を使うべきだと主張しているだろうが)。 – LukeH

+2

これらの提案は、可能ではあるが、関連するコンバージョンそれは、もちろん、DateTime値が持つ消費者の数に依存します。 –

+2

@ Sensai76おそらく、私は変換が面倒なオーバーヘッドになることは疑いますが(これは他のスレッドによってどのように使用されているかを知らなければ言うことは難しいですが)、それは何らかのオーバーヘッドより少なくなりますロック。 –

2

フィールドにアクセスを同期させるには、lockまたはMonitorクラスを使用する必要があります。

これは、DateTimeが値型であるためです。 MSDNから

からvolatile (C# Reference)

volatileキーワードは、これらのタイプの分野に適用することができます。

  • 参照型。
  • ポインタタイプ(安全でないコンテキスト内)。ポインタ自体はvolatileでもかまいませんが、ポインタが指すオブジェクトはvolatileではありません。つまり、「volatileへのポインタ」を宣言することはできません。
  • sbyte、byte、short、ushort、int、uint、char、float、およびboolなどの型。
  • byte、sbyte、short、ushort、int、またはuintのいずれかの基本タイプの列挙型。
  • 参照型として知られている汎用型パラメータ。
  • IntPtrおよびUIntPtr。

他の人が述べたように、あなたは時間を追跡するためにTicksを使用することができます。

2

あなたのコードはスレッドセーフではありません。一般に、32ビットまでの整数の割り当てはアトミックですが、64はアトミックである必要はありません。

には、DateTimeのティックを使用できます。これは、Int64をアトミックに格納できるためです。

しかし、ティックに切り替えると、ティックには62ビットしか使用されず、種類に対しては2ビットしか使用されないことがわかります。だからあなたはその種を失うことはありません。

getterとsetterをスレッドセーフにしても、十分であれば分かりません。あなたのゲッターが返す時間と実際にあなたが持っている時間を使って作業する時間との間で時間が変わることがあります。だからあなたの時間は、時代遅れになる可能性があります。

+0

これは、x64マシン用のx64アプリケーションです。それは問題ですか?いい視点ね。 – vtortola

+0

@vtortolaこれによると、64ビットの割り当てはアトミックになります。_ CLIは、プロセッサの自然なポインタサイズのサイズ(またはそれより小さい)である値型の変数の読み書きがアトミックであることを保証します。 CLRの64ビット版の64ビットオペレーティングシステムでC#コードを実行している場合、64ビットの倍精度浮動小数点数型(double bit)とlong整数の読み取りと書き込みもアトミックであることが保証されます。 C#言語はそれを保証するものではありませんが、ランタイム仕様は保証しません._ https://stackoverflow.com/a/11745471/67824 –

関連する問題