Roy*_*mir 5 .net c# multithreading .net-4.0
我一直在问自己:"为什么我只能使用锁定一个声明"......
(恕我直言 - 如果它的1次操作只是作为一项任务 - 所以不应该有问题......)?
然后我看到了这个:
作为一项基本规则,您需要锁定访问任何可写共享字段.即使在最简单的情况下 - 对单个字段进行分配操作 - 您也必须考虑同步.在下面的类中,Increment和Assign方法都不是线程安全的:
class ThreadUnsafe
{
static int _x;
static void Increment() { _x++; }
static void Assign() { _x = 123; }
}
Run Code Online (Sandbox Code Playgroud)
你能告诉我为什么这不是线程安全吗?我一直在运行许多脚本,无法找到任何问题......
这是一个示例,说明为什么您的示例不是线程安全的。最初,_x = 0。假设您并行Increment运行Assign。如果方法是线程安全的,则结果应该是100(如果在分配之前执行增量)或101(如果在分配之后执行增量)。
(编辑:请注意,每个线程都有自己的工作堆栈!)
Thread 1 (executing Increment) Thread 2 (executing Assign 100)
-----------------------------------------------------------------
read _x onto stack (= 0)
put 100 on top of stack
write top of stack to _x (= 100)
increment top of stack (= 1)
write top of stack to _x (= 1)
Run Code Online (Sandbox Code Playgroud)
_x是现在1,既不是100也不是101。
当然,您的增量方法可能被编译器编译为单个原子操作。但你不能依赖这一点,除非你使用的编译器特别保证它。
如果您使用锁,则会发生以下情况:
Thread 1 (executing Increment) Thread 2 (executing Assign 100)
-----------------------------------------------------------------
lock (success)
read _x onto stack (= 0)
lock (lock already taken;
| wait until Thead 1's lock is released)
increment top of stack (= 1) |
write top of stack to _x (= 1) |
unlock |
+> (success)
put 100 on top of stack
write top of stack to _x (= 100)
unlock
Run Code Online (Sandbox Code Playgroud)
结果就是现在100。基本上,锁确保两个锁定的块不会重叠。