i3a*_*non 51 .net c# concurrency datetime tearing
在C#设置中,只要变量的大小最大native int(即32位运行时环境中的4个字节和64位上的8个字节),变量的值就是原子级.在一个64位的环境,它包括所有的引用类型和最内置值类型(byte,short,int,long,等等).
设置更大的值不是原子的,并且可能导致仅更新部分内存的撕裂.
DateTime是一个结构,它只包含一个ulong包含其所有数据(Ticks和DateTimeKind)的字段,并且ulong在64位环境中本身是原子的.
这是否意味着它DateTime也是原子的?或者以下代码是否会在某些时候导致撕裂?
static DateTime _value;
static void Main()
{
for (int i = 0; i < 10; i++)
{
new Thread(_ =>
{
var random = new Random();
while (true)
{
_value = new DateTime((long)random.Next() << 30 | (long)random.Next());
}
}).Start();
}
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
Sco*_*ain 32
来自ECMA规范部分"I.12.6.6原子读写"
符合要求的CLI应保证
native int当对位置的所有写访问都相同时,对正确对齐的内存位置的读写访问权限不大于本机字大小(类型的大小)是原子的(参见§I.12.6.2)尺寸.原子写入除了写入之外不得改变任何位.除非使用显式布局控制(请参阅分区II(控制实例布局))来更改默认行为,否则不应大于自然字大小(a的大小native int)的数据元素.对象引用应被视为存储在本机字大小中.
A native int是IntPtrC#中的一个.
只要sizeof(IntPtr) >= sizeof(DateTime)运行时环境(也就是:以64位运行)[StructLayout(LayoutKind.Auto)]为止,并且它们不会将内部结构更改为具有未对齐字节的显式布局而不是当前具有的字节,则读取和写入DateTime结构(或遵循这些规则的任何其他结构都保证是ECMA规范的原子.
您可以通过在64位环境中运行以下代码来验证:
public unsafe static void Main()
{
Console.WriteLine(sizeof(DateTime)); // Outputs 8
Console.WriteLine(sizeof(IntPtr)); // Outputs 8
Console.WriteLine(sizeof(ulong)); // Outputs 8
}
Run Code Online (Sandbox Code Playgroud)
运行一些测试并基于上面的答案,可以说它今天是原子的.
我编写了一个测试来验证在N个线程的X迭代期间可以找到多少眼泪,用于Int64,DateTime和3个128,192和256尺寸的自定义结构 - 没有任何一个结构搞乱搞乱.
测试包括:
我的机器中的结果如下(Core i7-4500U,Windows 10 x64,.NET 4.6,无调试版本,平台目标:带代码优化的x64):
-------------- Trying to Tear --------------
Running: 64bits
Max Threads: 30
Max Reruns: 10
Iterations per Thread: 20000
--------------------------------------------
----- Tears ------ | -------- Size ---------
0 Int64 (64bits)
0 DateTime (64bits)
23 Struct128 (128bits)
87 Struct192 (192bits)
43 Struct256 (256bits)
----- Tears ------ | -------- Size ---------
0 Int64 (64bits)
0 DateTime (64bits)
44 Struct128 (128bits)
59 Struct192 (192bits)
52 Struct256 (256bits)
----- Tears ------ | -------- Size ---------
0 Int64 (64bits)
0 DateTime (64bits)
26 Struct128 (128bits)
53 Struct192 (192bits)
45 Struct256 (256bits)
----- Tears ------ | -------- Size ---------
0 Int64 (64bits)
0 DateTime (64bits)
46 Struct128 (128bits)
57 Struct192 (192bits)
56 Struct256 (256bits)
------------------- End --------------------
Run Code Online (Sandbox Code Playgroud)
测试代码可以在这里找到:https://gist.github.com/Flash3001/da5bd3ca800f674082dd8030ef70cf4e
| 归档时间: |
|
| 查看次数: |
2856 次 |
| 最近记录: |