C#的易失字段
当字段声明中含有 volatile 修饰符时,该声明引入的字段为易失字段。
由于采用了优化技术(它会重新安排指令的执行顺序),在多线程的程序运行环境下,如果不采取同步(如由 lock 语句所提供的)控制手段,则对于非易失字段的访问可能会导致意外的和不可预见的结果。这些优化可以由编译器、运行时系统或硬件执行。但是,对于易失字段,优化时的这种重新排序必须遵循以下规则:
读取一个易失字段称为易失读取。易失读取具有“获取语义”;也就是说,按照指令序列,所有排在易失读取之后的对内存的引用,在执行时也一定排在它的后面。
写入一个易失字段称为易失写入。易失写入具有“释放语义”;也就是说,按照指令序列,所有排在易失写入之前的对内存的引用,在执行时也一定排在它的前面。
这些限制能确保所有线程都会观察到由其他任何线程所执行的易失写入(按照原来安排的顺序)。一个遵循本规范的实现并非必须做到:使易失写入的执行顺序,在所有正在执行的线程看来都是一样的。易失字段的类型必须是下列类型中的一种:
引用类型。
类型 byte、sbyte、short、ushort、int、uint、char、float 或 bool。
枚举基类型为 byte、sbyte、short、ushort、int 或 uint 的枚举类型。
示例
产生下列输出:
result= 143
在本示例中,方法 Main 启动一个新线程,该线程运行方法 Thread2。该方法将一个值存储在叫做 result 的非易失字段中,然后将 true 存储在易失字段 finished 中。主线程等待字段 finished 被设置为 true,然后读取字段 result。由于 finished 已被声明为 volatile,主线程从字段 result 读取的值一定是 143。如果字段 finished 未被声明为 volatile,则对 finished 和 result 的写入的顺序就可能改变,这样,当主线程读取字段 result 时,它可能尚未被赋值(因而为初始值 0)。将 finished 声明为 volatile 字段可以防止这种不一致性。
更多技术分享在这里