c# - Task.IsCompleted 使用缓存标志的原因是什么?
问题描述
我正在查看 System.Threading.Tasks(.NET 标准 2.0)中 Task 的一些实现细节,我遇到了这段有趣的代码:
internal volatile int m_stateFlags;
...
public bool IsCompleted
{
get
{
int stateFlags = m_stateFlags; // enable inlining of IsCompletedMethod by "cast"ing away the volatiliy
return IsCompletedMethod(stateFlags);
}
}
// Similar to IsCompleted property, but allows for the use of a cached flags value
// rather than reading the volatile m_stateFlags field.
private static bool IsCompletedMethod(int flags)
{
return (flags & TASK_STATE_COMPLETED_MASK) != 0;
}
我从阅读 C# 参考指南中了解到 volatile 是为了防止编译器/运行时/硬件优化导致对字段的读/写重新排序。为什么在这种特定情况下将字段指定为 volatile 只是为了在通过将字段分配给变量来读取字段时忽略波动性?
这似乎是有意的,但我不清楚意图背后的原因。另外,“抛弃”波动性是一种常见的做法吗?在哪些情况下我想这样做与我绝对想避免它的情况?
非常感谢任何有助于我更清楚地理解这段代码的信息。
谢谢,
解决方案
volatile
是and的语法糖Volatile.Read
Volatile.Write
。它确保任何 CPU 将同时看到相同的数据。
所以它只读取一次 volatile 变量。那么这可能会在属性,方法中多次使用(失去易失性)。所以看起来它拍摄了变量的快照并对其值进行了几次计算。
internal volatile int m_stateFlags;
public bool IsCompleted
{
get
{
int stateFlags = m_stateFlags;
return IsCompletedMethod(stateFlags);
}
}
推荐阅读
- git - 如何修复 Git 中的“packet_write_wait: Connection to ... Broken pipe”错误
- sql - 有没有办法让我丢失的月份回到 SQL 中
- php - 转换为字符串时出错,导出到 excel
- c++ - 如何将图标添加到组合框左侧
- vue.js - Vue 动态组件 - 监视挂载
- javascript - 避免从导入中引入代码
- c# - 如何在 Startup.cs 中添加 HTTPS 重定向豁免?(ASP.NET 核心 2.1)
- swift - iBeacon swift 在检测 Beacon 时需要“requestWhenInUseAuth”吗?
- angular - 角度如何为模板驱动表单的交叉字段验证编写指令
- amp-html - 有没有办法在 AMP 上创建一个超链接,点击后会跳转到同一 AMP 页面上的某个部分?