我知道在没有锁定的情况下,C++ 中的增量操作不是原子的。
JVM 会在
iinc
指令的实现上添加任何锁吗?
不,不是的
您需要使用
synchronized
关键字或使用 AtomicXXX
方法来保证线程安全。
更新:
public synchronized void increment() {
c++;
}
或
AtomicInteger integer = new AtomicInteger(1);
//somewhere else in code
integer.incrementAndGet();
另请阅读:iinc 在 Java 中是原子的吗?
您问题的答案取决于您指的是
IINC
指令,还是其他答案所指的 ++
运算符。
在静态或实例字段上使用
++
无非是获取、增量和设置,因此它不是原子的(其他答案更详细地解释了这一点)。
但是既然你问
IINC
instruction 是否是原子的,这不是真正的答案。事实上,这个问题的答案都没有涉及指令,所有答案似乎都是基于实例或静态字段上使用的运算符。
IINC
指令仅对局部变量进行操作。顾名思义,它们是本地的,只能在非常有限的范围内访问。因此,不可能从另一个线程访问局部变量。这意味着指令是否是原子的并不重要。
不是的,它可能会导致真正的问题。这个测试应该打印 200000000 但由于线程干扰而没有打印
static int n;
public static void main(String[] args) throws InterruptedException {
Runnable r = new Runnable() {
public void run() {
for(int i = 0; i < 100000000; i++) {
n++;
}
}
};
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(n);
}
请注意,
volatile
并不能解决问题。
不,它不是原子的,字节码可以与其他线程交错。
i++ 在 java 中不是原子的。
最好用
AtomicInteger atomic= new AtomicInteger(1);
有类似定义的方法
atomic.getAndDecrement();
atomic.getAndIncrement();
atomic.decrementAndGet();
atomic.incrementAndGet();
使用上述方法的任何操作都是原子的。
此类位于
java.util.concurrent.atomic
包下。
Java 1.5
为线程安全和线程并发添加了许多功能。
它不是原子的。这是静态 int 后递增生成的字节代码:
0 getstatic 18; // Load value of variable.
3 iconst_1;
4 iadd;
5 putstatic 18; // Store value.