C# 从实例化对象读取属性是否线程安全?
我是否可以安全地从多个线程中读取实例化单例的C# 从实例化对象读取属性是否线程安全?,c#,thread-safety,singleton,C#,Thread Safety,Singleton,我是否可以安全地从多个线程中读取实例化单例的IsBusy布尔属性,而不会导致任何线程安全问题,或者我是否已经处于危险水域中?如果您已按以下方式定义属性IsBusy,那么您肯定会遇到线程安全问题: public bool IsBusy { get; set; } 这里最大的问题是可以在设置值之前检查并更改值。这意味着你有比赛条件。解决这一问题的一种方法是: // this is going to keep trying to lock until it succeeds, after which
IsBusy
布尔属性,而不会导致任何线程安全问题,或者我是否已经处于危险水域中?如果您已按以下方式定义属性IsBusy
,那么您肯定会遇到线程安全问题:
public bool IsBusy { get; set; }
这里最大的问题是可以在设置值之前检查并更改值。这意味着你有比赛条件。解决这一问题的一种方法是:
// this is going to keep trying to lock until it succeeds, after which it
// will do whatever work needs done.
while (true) {
bool lockObtained = false;
lock (objectInstance) {
if (!objectInstance.IsBusy) {
lockObtained = true;
objectInstance.IsBusy = true;
}
}
if (lockObtained) {
// good to go here
// and don't forget to clear the IsBusy
objectInstance.IsBusy = false;
break;
}
}
使用内置的.NET锁定机制来锁定对象,这样您就可以检查和设置,而不用担心中间的进程抢占。
如果您已经定义了属性<代码>忙> /代码>,那么您肯定可以有线程安全问题:public bool IsBusy { get; set; }
这里最大的问题是可以在设置值之前检查并更改值。这意味着你有比赛条件。解决这一问题的一种方法是:
// this is going to keep trying to lock until it succeeds, after which it
// will do whatever work needs done.
while (true) {
bool lockObtained = false;
lock (objectInstance) {
if (!objectInstance.IsBusy) {
lockObtained = true;
objectInstance.IsBusy = true;
}
}
if (lockObtained) {
// good to go here
// and don't forget to clear the IsBusy
objectInstance.IsBusy = false;
break;
}
}
使用内置的.NET锁定机制来锁定对象,这样您就可以检查和设置,而不用担心中间的进程抢占。
< P>除非有内存障碍,否则潜在的危险水域,如果值可以改变的话。 让我们把这个方程中的单态部分去掉,因为它不是特别相关。考虑这个简单的例子:// Not safe!
public class BusyIndicator
{
public bool IsBusy { get; set; }
}
现在,如果你有一条线,沿着以下线:
foo.IsBusy = true;
// do some work
foo.IsBusy = false;
另一个线程,仅在IsBusy
设置为true后启动,它具有:
// Do some work
while (foo.IsBusy) { }
。。。那么第二条线可能会永远旋转。。。没有内存障碍来确保它“看到”第一个线程的更改
您可以使用锁定或使用联锁
安全地执行此操作,例如:
// Safe (in terms of memory barriers)
public class BusyIndicator
{
private int busy = 0;
public bool IsBusy
{
get { return Interlocked.CompareExchange(ref busy, 0, 0) == 1; }
set { Interlocked.Exchange(ref busy, value ? 1 : 0); }
}
}
除非你有任何记忆障碍,否则你可能会陷入危险的境地,如果这个值可能会改变的话 让我们把这个方程中的单态部分去掉,因为它不是特别相关。考虑这个简单的例子:
// Not safe!
public class BusyIndicator
{
public bool IsBusy { get; set; }
}
现在,如果你有一条线,沿着以下线:
foo.IsBusy = true;
// do some work
foo.IsBusy = false;
另一个线程,仅在IsBusy
设置为true后启动,它具有:
// Do some work
while (foo.IsBusy) { }
。。。那么第二条线可能会永远旋转。。。没有内存障碍来确保它“看到”第一个线程的更改
您可以使用锁定或使用联锁
安全地执行此操作,例如:
// Safe (in terms of memory barriers)
public class BusyIndicator
{
private int busy = 0;
public bool IsBusy
{
get { return Interlocked.CompareExchange(ref busy, 0, 0) == 1; }
set { Interlocked.Exchange(ref busy, value ? 1 : 0); }
}
}
取决于它是如何实现的。@Vlad:这取决于你所说的“线程安全”是什么意思。例如,如果valid可以由另一个线程更改,使用一个没有内存障碍的简单字段实现,并且您必须在另一个线程中看到更改,那么这是不安全的。@JeremyHolovacs您有4个不同的人要求您澄清问题,因为您的问题,信息严重不足,不需要真正负责。试图回答问题的人必须自己举出例子,试着猜测你在问什么,因为你在问题中没有提供足够的信息。在提出这个问题之前,你显然也没有对这个问题做过什么研究。“总而言之,我认为没有理由对这个问题投反对票,因为它没有展示研究成果,不清楚,不可回答,而且毫无用处。”杰里米霍洛瓦茨·乔恩猜到了你在做什么。他说你可能有问题。他不知道。他不知道,那是因为这个问题没有足够的信息来回答。他必须发明自己的问题,这样他才能回答,因为你的问题无法回答。如果你想知道你的问题遗漏了什么,从所有现有的评论开始,询问你更多的信息(顺便说一下,包括Jon)。这至少会给你一个开始的地方。@JeremyHolovacs不,答案不是否定的。回答是“也许,我们不知道,请提供更多信息。”即使Jon不能说“不”,他也只能说,“也许,但这里有一些其他情况,答案是否定的。”这取决于它的实现方式。@Vlad:这取决于你的意思“线程安全“。例如,如果valid可以由另一个线程更改,使用一个没有内存障碍的简单字段实现,并且您必须在另一个线程中看到更改,那么这是不安全的。@JeremyHolovacs您有4个不同的人要求您澄清问题,因为您的问题,信息严重不足,不需要真正负责。试图回答问题的人必须自己举出例子,试着猜测你在问什么,因为你在问题中没有提供足够的信息。在提出这个问题之前,你显然也没有对这个问题做过什么研究。“总而言之,我认为没有理由对这个问题投反对票,因为它没有展示研究成果,不清楚,不可回答,而且毫无用处。”杰里米霍洛瓦茨·乔恩猜到了你在做什么。他说你可能有问题。他不知道。他不知道,那是因为这个问题没有足够的信息来回答。他必须发明自己的问题,这样他才能回答,因为你的问题无法回答。如果你想知道你的问题遗漏了什么,从所有现有的评论开始,询问你更多的信息(顺便说一下,包括Jon)。这至少会给你一个开始的地方。@JeremyHolovacs不,答案不是否定的。回答是“也许,我们不知道,请提供更多信息。”即使是Jon也不能说“不”,他只能说,“也许,但在其他情况下,答案是否定的。”首先,你的财产没有阅读你的领域。第二,如果总是false,那么指示您是否忙又有什么意义呢?如果没有来自构造函数的初始值,这是非常无用的,而且它在语义上是一个常量,您只想避免编译器进行常量内联。@Servy我同意。我