我觉得我不应该关心线程安全访问/写入
public static int MyVar = 12;
在ASP .NET中。
我从各种用户线程读取/写入此变量。我们假设这个变量将存储某个按钮/链接的点击次数。
我的理论是没有线程可以同时读/写这个变量。它只是一个4字节的简单变量。
我确实关心线程安全,但仅适用于参考对象和List实例或需要更多周期来读取/更新的其他类型。
我的推定错了吗?
修改
我理解这取决于我的情景,但这不是问题的关键。问题是:是否可以使用(static int)变量编写线程安全代码而不使用lock关键字?
编写正确的代码是我的问题。答案似乎是:是的,如果您编写正确而简单的代码,而不是太复杂,您可以创建线程安全函数而无需使用lock关键字。
答案 0 :(得分:4)
如果一个线程只是设置值而另一个线程读取该值,则不需要锁定;读写是原子的。但是如果多个线程可能正在更新它并且还在读取它以进行更新(例如,增量),那么你肯定需要某种同步。如果只有一个线程即使是增量也会更新它,那么我认为不需要同步。
编辑(三年后)可能还需要在声明中添加volatile
关键字,以确保值的读取始终获得最新值(假设申请)。
答案 1 :(得分:2)
不幸的是,线程“安全”的概念太模糊,没有意义。如果你问是否可以从多个线程读取和写入它而不会在程序运行期间崩溃,答案肯定是肯定的。如果您还要求变量保证是旧值还是新值而不存储任何损坏的中间值,则此数据类型的答案几乎肯定是肯定的。
但如果你的问题是“如果我从多个线程访问它,我的程序是否会正常工作”,那么答案完全取决于你的程序在做什么。例如,如果您在大多数编程语言中重复运行2个线程中的以下伪代码,最终您将点击该断言。
if MyVar >= 1:
MyVar = MyVar - 1
assert MyVar >= 0
答案 2 :(得分:2)
int
这样的原语在读/写是原子的意义上是线程安全的。但与大多数类型一样,您可以使用更复杂的操作进行适当的检查。例如,if (x > 0) x--;
在多线程场景中会出现问题,因为x
可能会在if条件检查和减少之间发生变化。
答案 3 :(得分:1)
对32位或更少的字段进行简单的读或写总是原子的。但是你应该提供你的读/写代码,以确保它是线程安全的。
答案 4 :(得分:1)
查看此帖子:http://msdn.microsoft.com/en-us/magazine/cc163929.aspx
它解释了为什么需要在此场景中同步对整数的访问
答案 5 :(得分:1)
尝试Interlocked.Increment()或Interlocked.Add(),你会是对的。您的代码复杂性将是相同的,但您真的不必担心。如果您不担心在计数器中丢失几次点击,您可以继续保持原样。
答案 6 :(得分:1)
读取或写入整数是原子的。然而,阅读和写作并不是原子的。因此,如果你有一个写入的线程和许多读取的线程,你可以在没有锁定的情况下离开。
但是,即使操作是原子操作,仍然存在潜在的多线程问题。为了保证一个线程可以看到另一个线程可以看到它写入的值,您需要一个内存屏障。否则,编译器可以优化代码,使变量保留在寄存器中(甚至完全优化操作),因此从一个线程到另一个线程的变化是不可见的。
您可以明确地建立记忆障碍(volatile
或Thread.MemoryBarrier
),或使用Interlocked
类或lock
声明(Monitor
)。