我一直在開發多線程算法,我對C#中的線程之間共享類成員存在一些疑問。C#:在線程之間共享類成員
我們假設我們有兩個類Algorithm和Processor。處理器有一個 主要方法DoWork和其他可用資源方法偶爾調用以更改可用資源的數量進行處理。 方法運行和UpdateResources在算法對象由兩個不同的線程調用,可能在不同核心上的工作。
是否有可能是_processor變量將被存儲在CPU的緩存,絕不會被上傳到內存中,並AvaliableResources將永遠不會被調用,因爲_processor是空的第二個線程?
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
「的第二個線程」 - 既不是線程是第一或第二個 - 他們只是不同的線程;在「Run」甚至被調用之前,「第二個」線程可以完成它所需的一切......在這種情況下:「_processor」的值是多少? –