这个问题不是关于竞争条件,原子性,或者为什么要在代码中使用锁.我已经知道了.
更新:我的问题不是"存在易失性存储器的奇怪现象"(我知道它确实存在),我的问题是"没有.NET运行时抽象,所以你永远不会看到它".
请参阅http://www.yoda.arachsys.com/csharp/threads/volatility.shtml 和关于字符串属性本身线程安全的第一个答案吗?
(它们实际上是同一篇文章,因为一个引用另一个.)一个线程设置bool而另一个线程循环永远读取bool - 那些文章声称读取线程可能缓存旧值并且从不读取新值,所以因此你需要一个锁(或使用volatile关键字).他们声称以下代码可能永远循环.现在我同意锁定变量是一种好习惯,但我无法相信.NET运行时会真正忽略内存值的变化,如文章所述.我理解他们关于易失性内存与非易失性内存的讨论,我同意他们在非托管中有一个有效的观点代码,但我无法相信.NET运行时将无法正确地抽象出来,以便下面的代码能够满足您的期望.这篇文章甚至承认代码"几乎可以肯定"有效(虽然不能保证),所以我就索赔要求BS.任何人都可以验证以下代码是否真的有效?是否有人能够得到一个案例(也许你不能总是重现它)这个失败的地方?
class BackgroundTaskDemo
{
private bool stopping = false;
static void Main()
{
BackgroundTaskDemo demo = new BackgroundTaskDemo();
new Thread(demo.DoWork).Start();
Thread.Sleep(5000);
demo.stopping = true;
}
static void DoWork()
{
while (!stopping)
{
// Do something here
}
}
}
Run Code Online (Sandbox Code Playgroud) 如何判断由 发起的延续TaskCompletionSource.TrySetResult是同步执行还是异步执行?
例如:
// class A
void RegisterNotification(TaskCompletionSource<object> tcs)
{
this.source.NotificationEvent += (s, eData) =>
{
Debug.WriteLine("A.before");
tcs.TrySetResult(eData.Result);
Debug.WriteLine("A.after");
DoProcessingA();
};
}
// class B
async Task RequestNotificationAsync()
{
var tcs = new TaskCompletionSource<object>();
this.a.RegisterNotification(tcs);
Debug.WriteLine("B.before");
var data = await tcs.Task;
Debug.WriteLine("B.after");
DoProcessingB();
}
Run Code Online (Sandbox Code Playgroud)
如果在NotificationEvent具有与发生位置不同的同步上下文的线程上触发await tcs.Task,则调试输出将为:
B.之前 A.之前 A.之后 B.之后
也就是说,await tcs.Task延续是异步执行的。如果它在同一个同步上下文上触发(或者如果两个地方都没有同步上下文),则输出将为:
B.之前 A.之前 B.之后 A.之后
也就是说,延续是同步执行的。
有没有办法预测里面的这个顺序RegisterNotification?
我可以保存SynchronizationContext.Current在里面RegisterNotification,稍后打电话时进行比较tcs.TrySetResult。但这并不一定意味着这await tcs.Task将发生在我保存的上下文中。
理论上,如果我能预测这一点,我也许能够用它来诊断和防止潜在的死锁。
c# multithreading asynchronous task-parallel-library async-await
我有一个带有后备字段的属性,我想让它确保线程安全(获取和设置)。get 和 set 方法除了设置和返回没有逻辑。
我认为有两种方法可以将逻辑封装在属性 self(易失性和锁定)中。我对两者的理解是正确的还是我犯了任何错误?
下面是我的例子:
public class ThreadSafeClass
{
// 1. Volatile Example:
private volatile int _processState_1;
public int ProcessState_1
{
get { return _processState_1; }
set { _processState_1 = value; }
}
// 2. Locking Example:
private readonly object _processState_2Lock = new object();
private int _processState_2;
public int ProcessState_2
{
get
{
lock (_processState_2Lock)
{
return _processState_2;
}
}
set
{
lock (_processState_2Lock)
{
_processState_2 = value;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)