C# async和await是否产生acquire和release语义?
对于从C# async和await是否产生acquire和release语义?,c#,.net,async-await,language-lawyer,memory-model,C#,.net,Async Await,Language Lawyer,Memory Model,对于从async方法返回是否总是产生发布语义,以及wait是否总是产生获取语义,我找不到明确的答案。我假设是的,因为否则任何async/await代码都会是雷区 下面是一个例子:返回值是否保证都是100*2和12345*2,没有任何明确的锁或障碍 private static async Task<(int, int)> AMethod() { // Runs on the original thread: var x = 100; var y = 12345
async
方法返回是否总是产生发布语义,以及wait
是否总是产生获取语义,我找不到明确的答案。我假设是的,因为否则任何async/await
代码都会是雷区
下面是一个例子:返回值是否保证都是100*2
和12345*2
,没有任何明确的锁或障碍
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);
}
private静态异步任务AMethod()
{
//在原始线程上运行:
var x=100;
变量y=12345;
var task=task.Run(()=>
{
//可以在其他线程上运行:
x*=2;
y*=2;
//此处隐式返回,标记任务已完成。
//是否释放语义?
});
等待任务;//是否获取语义?
//在原始线程上运行:
返回(x,y);
}
编辑:当然,
Task.Run
还需要生成一个发布,并且在开始运行任务的代码时需要获取。忘记原始问题中的值。是的,返回值都保证为100*2
和12345*2
,没有任何明确的锁或障碍
在这种情况下,产生内存障碍的是任务.Run
,而不是wait
引述:
以下命令隐式生成完整的围栏:
- C#的锁语句(Monitor.Enter/Monitor.Exit)
- 联锁类上的所有方法(我们将很快介绍这些)
- 使用线程池的异步回调-包括异步委托、APM回调和任务延续
- 设置和等待信令构造
- 任何依赖于信号的东西,如开始或等待任务
int x = 0;
Task t = Task.Factory.StartNew (() => x++);
t.Wait();
Console.WriteLine (x); // 1
Task.Run
包装ThreadPool.UnsafeQueueUserWorkItem
,它属于“使用线程池的异步回调”
有关创建内存障碍的内容的更全面列表,请参阅。添加
wait任务。配置wait(false)
。然后你肯定不能保证x和y将是100*2
和12345*2
@YauhenSampir否,这对问题没有任何影响。相关:@YauhenSampir如果发布和获取都存在,无论如何,你仍然会得到一个好结果。ConfigureAwait(false)
。当然,获取和释放也是开始任务所必需的,而不仅仅是完成任务。嗯。谢谢你提到那件事。将编辑问题。