异步并等待产生获取和释放语义吗? [英] Do async and await produce acquire and release semantics?
问题描述
对于从async
方法返回是否总是产生释放语义以及await
是否总是产生获取语义,我找不到明确的答案.我认为是的,因为否则,任何async/await
代码都将是雷区?
I couldn't find a clear answer about whether returning from an async
method always produces release semantics and whether await
always produces acquire semantics. I assume yes, because otherwise any async/await
code would be a minefield?
所以这是一个例子:是否保证返回的值都为100*2
和12345*2
,而没有任何显式的锁或障碍?
So here's an example: are returned values both guaranteed to be 100*2
and 12345*2
, without any explicit locks or barriers?
private static async Task<(int, int)> AMethod()
{
// Runs on the original thread:
var x = 100;
var y = 12345;
var task = Task.Run(() =>
{
// Can run on another thread:
x *= 2;
y *= 2;
// Implicit return here, marking the task completed.
// Release semantics or not?
});
await task; // Acquire semantics or not?
// Runs on the original thread:
return (x, y);
}
当然,Task.Run
还需要产生一个发行版,并且在开始运行任务的代码时需要获取.忘记了原始问题中的内容.
Of course, Task.Run
also needs to produce a release and an acquire is needed when starting to run the task's code. Forgot about those in the original question.
推荐答案
是的,保证返回的值都是100*2
和12345*2
,没有任何显式的锁或障碍.
Yes, the returned values are both guaranteed to be 100*2
and 12345*2
, without any explicit locks or barriers.
在这种情况下,产生内存障碍的是Task.Run
,而不是await
.
It's the Task.Run
, not the await
, which produces the memory barrier in this case.
引用 C#中出色的Albahari线程:
以下内容隐式生成完整的篱笆:
The following implicitly generate full fences:
- C#的lock语句(Monitor.Enter/Monitor.Exit)
- Interlocked类上的所有方法(我们将在稍后介绍)
- 使用线程池的异步回调-其中包括异步委托,APM回调和任务延续
- 设置并等待信令构造
- 任何与信号有关的东西,例如启动或等待任务
- C#'s lock statement (Monitor.Enter/Monitor.Exit)
- All methods on the Interlocked class (we’ll cover these soon)
- Asynchronous callbacks that use the thread pool — these include asynchronous delegates, APM callbacks, and Task continuations
- Setting and waiting on a signaling construct
- Anything that relies on signaling, such as starting or waiting on a Task
借助最后一点,以下内容是线程安全的:
By virtue of that last point, the following is thread-safe:
int x = 0;
Task t = Task.Factory.StartNew (() => x++);
t.Wait();
Console.WriteLine (x); // 1
Task.Run
包装ThreadPool.UnsafeQueueUserWorkItem
,它属于使用线程池的异步回调".
Task.Run
wraps ThreadPool.UnsafeQueueUserWorkItem
, which falls under "Asynchronous callbacks that use the thread pool".
请参阅内存屏障生成器,以获取更全面的创建内存屏障的信息.
See Memory barrier generators for a more comprensive list of things that create memory barriers.
这篇关于异步并等待产生获取和释放语义吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!