重複の可能性:
C# のスレッド化とブロッキング
どちらのアプローチが優れているかを効果的に判断しようとしています。
現在、遅延読み込み方式で読み込まれるエンティティを公開するシングルトン インスタンスがあります。それぞれにいくつかの利点がある 3 つのアプローチをリストしました。最初のアプローチは、スレッドの安全性を確保するために二重ロック パターンのみに依存します。2 番目のアプローチはロックを使用しませんが、レースの場合に二重ロードの可能性があります。3 番目のアプローチは、私が非常に気に入っているソリューションを実際に使用しています。(System.Lazy)。
何らかの理由で、2 番目のアプローチ (System.Thread.InterLocked) に何か問題があると感じていますが、それを特定することはできません。あるアプローチを他のアプローチよりも優先する理由はありますか? これについては、以前の投稿で取り上げましたが、今後は 3 番目のオプションが進むべき道だと感じました。
設計を説明できるように、コードを最小限に抑えました。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TPLDemo
{
public class SomeEntity
{
}
public class MultiThreadedManager
{
private static readonly System.Lazy<MultiThreadedManager> instance = new Lazy<MultiThreadedManager>(() => { return new MultiThreadedManager(); });
private readonly object _syncRoot = new object();
private List<SomeEntity> _inMemoryEntities = null;
private List<SomeEntity> _inMemoryEntitiesUsingLockFreeApproach = null;
private System.Lazy<List<SomeEntity>> _inMemoryUsingLazy = new Lazy<List<SomeEntity>>(() => { return MultiThreadedManager.Instance.LoadFromSomewhere(); });
public static MultiThreadedManager Instance
{
get { return instance.Value; }
}
public IEnumerable<SomeEntity> LazyEntities
{
get
{
return _inMemoryUsingLazy.Value;
}
}
public IEnumerable<SomeEntity> LocklessEntities
{
get
{
if (_inMemoryEntitiesUsingLockFreeApproach == null)
{
do
{
// Is it possible multiple threads hit this at the same time?
} while (System.Threading.Interlocked.CompareExchange<List<SomeEntity>>(ref _inMemoryEntitiesUsingLockFreeApproach, this.LoadFromSomewhere(), null) != null);
}
return _inMemoryEntitiesUsingLockFreeApproach;
}
}
/// <summary>
/// This is thread safe but it involved some locking.
/// </summary>
public IEnumerable<SomeEntity> Entities
{
get
{
if (_inMemoryEntities == null)
{
lock (_syncRoot)
{
if (_inMemoryEntities == null)
{
List<SomeEntity> list = this.LoadFromSomewhere();
_inMemoryEntities = list;
}
}
}
return _inMemoryEntities;
}
}
private List<SomeEntity> LoadFromSomewhere()
{
return new List<SomeEntity>();
}
public void ReloadEntities()
{
// This is sufficient becasue any subsequent call will reload them safely.
_inMemoryEntities = null;
// This is sufficient becasue any subsequent call will reload them safely.
_inMemoryEntitiesUsingLockFreeApproach = null;
// This is necessary becasue _inMemoryUsingLazy.Value is readonly.
_inMemoryUsingLazy = new Lazy<List<SomeEntity>>(() => { return MultiThreadedManager.Instance.LoadFromSomewhere(); });
}
}
}