我一直在开发多线程算法,我对在C#中的线程之间共享类成员有一些疑问。
假设我们有两个类Algorithm和Processor。处理器有一个 主方法 DoWork 和其他 AvaliableResources 方法,偶尔会调用它来更改可用资源的数量以进行处理。 算法对象中的 Run 和 UpdateResources 方法由两个不同的线程调用,可能在不同的Core上工作。< / p>
是否可能 _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);
}
}
答案 0 :(得分:0)
如果您想要访问,则2替代方案是错误的 以这种方式_processor obj。
无论如何,处理器中应该为null,因为DoWork运行速度更快。 尝试在睡眠的第一个线程中查找相同的秒,并检查是否可以执行。
您的代码未提供足够的信息以便以正确的方式提供建议。
使用volatile关键字是正确的,但如果Run is fast available不是call never
修改
好的,好的例子。但问题是在执行UpdateResources之前运行完成的主要工作程序。
如果您想在等待之前执行两次UpdateResources
,则在等待后插入执行_processor= null
的新方法。
在某种程度上,每次使用此代码时,每次在等待之前调用UpdateResources
,您的风险都是_processor为空。
在等待之前取决于你想要的东西