私はマルチスレッドアルゴリズムを開発しており、C#でスレッド間でクラスメンバーを共有することにいくつかの疑問があります。C#:スレッド間でクラスメンバーを共有する
アルゴリズムとプロセッサの2つのクラスがあるとします。プロセッサは メインメソッドDoWorkと追加のAvaliableResourcesメソッドがあり、処理のために使用可能なリソースの数を変更することがあります。 方法実行とアルゴリズムオブジェクトでUpdateResourcesは、おそらく別のコアで作業し、2つの異なるスレッドによって呼び出されます。
はそれが可能変数は、CPUのキャッシュに保存され、メモリにアップロードされることはありません_processorされ、_processorが第二のスレッドのためにnullであるため、AvaliableResourcesが呼び出されることはありませんでしょうか?
class Processor
{
public void DoWork() { ... }
public void AvaliableResources(int x) { ... }
}
class Algorithm
{
private Processor _processor;
public void Run()
{
_processor = new Processor();
_processor.DoWork();
_processor = null;
}
public void UpdateResources(int x)
{
_processor?.AvaliableResources(x);
}
}
同期の問題がある場合は、次のコードは、それのための解決策だろうか?
オルタナティブ1
class Processor
{
public void DoWork() { ... }
public void UpdateResources(int x) { ... }
}
class Algorithm
{
private volatile Processor _processor; // added volatile keyword
public void Run()
{
_processor = new Processor();
_processor.DoWork();
_processor = null;
}
public void UpdateResources(int x)
{
_processor?.UpdateResources(x);
}
}
オルタナティブ2
class Processor
{
public void DoWork() { ... }
public void UpdateResources(int x) { ... }
}
class Algorithm
{
private Processor _processor;
public void Run()
{
_processor = new Processor();
Thread.MemoryBarrier(); // Added memory barier
_processor.DoWork();
_processor = null;
}
public void UpdateResources(int x)
{
Thread.MemoryBarrier(); // Added memory barier
_processor?.UpdateResources(x);
}
}
編集: あなたはコメントで示唆したように、より良い説明のコードを参照してください。
class Processor
{
private int resources = Environment.ProcessorCount;
public void DoWork()
{
/*do some long running job using avaliable resources*/
}
public void UpdateResources(int x)
{
resources = x;
}
}
class Algorithm
{
private volatile Processor _processor;
public void Run()
{
_processor = new Processor();
_processor.DoWork();
_processor = null;
}
public void UpdateResources(int x)
{
_processor?.UpdateResources(x);
}
}
class Program
{
static void Main(string[] args)
{
var algorithm = new Algorithm();
var result = Task.Run(() => algorithm.Run());
// The resources were required for other staff and are reduced
algorithm.UpdateResources(1);
// The resources are reassigned for the long running algorithm
algorithm.UpdateResources(10);
// wait until the algorithm finishes
result.Wait();
// this update should have no effect as the Run method has finished and _processor is null
algorithm.UpdateResources(10);
}
}
を
コードを実行するとどうなりますか? – Fabulous
また、https://stackoverflow.com/questions/3556351/why-we-need-thread-memorybarrierがクエリ「 – Fabulous
」を「第2スレッド用」に指定していない場合も考慮してください。どちらのスレッドも第1または第2のスレッドではありません。異なるスレッド。 「2番目」のスレッドは、 'Run'も呼び出される前に必要なすべてを行っている可能性があります。その場合、' _processor'の値は何ですか? –