class ABC implements Runnable {
private static int a;
private static int b;
public void run() {
}
}
我有一个如上所述的Java类 . 我有这个类的多个线程 . 在 run()
方法中,变量 a
& b
每次递增几次 . 在每个增量上,我将这些变量放在Hashtable中 .
因此,每个线程都会增加两个变量并将它们放在Hashtable中 . 如何使这些操作线程安全?
4 回答
我会使用AtomicInteger,它被设计为线程安全的并且易于使用并且给应用程序带来绝对最小的同步开销:
取决于什么需要线程安全 . 对于这些
int
原语,您需要将它们替换为AtomicInteger
,或者仅在synchronized
方法或块中使用它们 . 如果你需要让你的跨线程Hashtable线程安全,你不需要做任何事情,因为它已经同步 .使用
synchronized
方法,例如如果你通过单个实例访问静态,上面是好的,但是如果你有多个实例,那么你需要在一些静态对象上进行同步 - 比如(未经测试) .
在方法中
注意:这些方法假设您希望在一个原子动作中增加
a
和b
,其他答案突出显示如何使用原子单独增加它们 .我想补充一些关于这个问题答案的细节 .
首先,OP询问:
在回答这个问题之前,我们需要达到 thread safe 的一致性 . 我最喜欢的定义是来自"Java Concurrency In Practice"而且它是
如果您同意该定义,则意味着我们在进一步讨论之前达到一致性 . 让's return to the operations you meant, it' s
a++
和b++
,在增量之后,你将它们放入HashTable
.对于
a++
操作,它实际上不是单个操作 . 它服从 read modify write 的模型 . 如您所见,它实际上包含三个单独的步骤 . 读取值,添加一个值并保存回来 . 如果有两个线程同时读取变量a
,值为1
,则在修改并保存后退操作 . 该值将为2
,但实际上应为3
. 为了避免这种情况发生,就像其他人建议的那样,您可以直接使用AtomicInteger
而不是int
类型 .AtomicInteger
将保证一些操作,如递增以原子方式执行 . 这意味着, read modify write 操作无法分割,并将作为一个单独的步骤执行 .之后,OP希望将值保存到HashTable中 . HashTable是一个线程安全的容器,不需要其他同步 .
希望这个澄清可以帮助别人以其他方式 . 谢谢 .