需要

2017-01-13 11 views
1

上の同期オブジェクトを作成します。私は、このオブジェクトは以前に明らかな理由もなく連載されたのDataContractの一部であった同期オブジェクト需要

[DataContract] 
class C1 
{ 
    [DataMember] 
    private object mySyncObject = new object(); 
} 

に含まれているクラスを持っています。データが含まれていないので、私は同期オブジェクトのDataMemberを省略しました。しかし、DataContractSerializerはデシリアライズ時にデフォルトのctorを呼び出さないため、実行時にNullReferenceExceptionsが使用されます。

lock(mySyncObject) // NullReferenceException 

今、私はプロパティでロックオブジェクトへのアクセスをカプセル化し、マルチスレッドアクセスは、プロパティがnullまたは異なるオブジェクトを返すために発生しないことを確実にしたいと思います。

私の改定オブジェクトは、今ではそう簡単にすることができ

[DataContract] 
class C1 
{ 
    private volatile object mySyncObject = new object(); 

    object SyncObject 
    { 
     get 
     { 
      if (mySyncObject == null) 
      { 
       Interlocked.CompareExchange<object>(ref mySyncObject, new object(), null); 
      } 
      return mySyncObject; 
     } 
    } 
} 

のように見えるか、私はここに潜在的な競合状態を見逃していますか?

答えて

1

atomic operationであるため、競合が発生する可能性はありません。むしろLazy<T>の実装と同様の実装を作成しました。

非常によく似た実装について議論しているこの例では、blogという素晴らしい例があります(この理由から、実装をやり直すことはもうありません)。直列化復元が行われた後のOPに代わるもので



オリジナルの答えは、のように、あなたもOnDeserializedAttributeの使用がmySyncObjectを初期化するために作ることができ、別の方法として実装

を提案しました以下の例

[DataContract] 
class C1 
{ 
    private object mySyncObject = new object(); 

    [OnDeserialized] 
    internal void OnDeserialized(StreamingContext context) 
    { 
     mySyncObject = new object(); 
    } 
} 

このようにして、そして、デシリアライズが行われた直後にメソッドが呼び出され、mySyncObjectが初期化されます。

これは、コメントで説明したように、DataContractSerializer,BinaryFormatter,JSON.Netと互換性があります。 DataContractSerializerは、デフォルトコンストラクタを使用していない理由について

詳しい情報は、このanswer

+0

まあで見つけることができ、実際に私がDataContractsではない別のシリアライザを使用するコードをリファクタリングしたいと思います。制約は、コードが新しい(Json.NET)と古いシリアライザで動作するだけであることです。したがって、シリアライザに依存しているかどうかにかかわらず、特定のシリアライザアトリビュートマジックに依存したくありません。 –

+0

@AloisKrausもっと多くの発見で私の答えを更新しました:) – Icepickle

+0

私はちょうど私が私の側で愚かなエラーで何かを壊していないことを確認したいと思っていました。 –

関連する問題