10

我知道在没有锁定的情况下,增量操作在 C++ 中不是原子的。

iincJVM 会在其指令执行上添加任何锁吗?

4

6 回答 6

16

不,这不对

  • 检索 c 的当前值。
  • 将检索到的值增加 1。
  • 将增加的值存储回 c 中。

原子性和线程干扰的 Java 文档

您需要使用synchronized关键字或使用AtomicXXX方法来确保线程安全。

更新

public synchronized void increment() {
    c++;
}

或者

AtomicInteger integer = new AtomicInteger(1);
//somewhere else in code
integer.incrementAndGet();

另请阅读:Java 中的 iinc 是原子的吗?

于 2013-03-08T05:38:16.613 回答
12

您的问题的答案取决于您是指IINC指令,还是其他答案所指的++操作员。

在静态或实例字段上使用++无非就是获取、递增和设置,因此它不是原子的(其他答案更详细地解释了这一点)。

由于您询问该IINC 指令是否是原子的,因此这不是真正的答案。事实上,这个问题的答案都没有解决指令,所有这些似乎都是基于在实例或静态字段上使用的运算符。


IINC指令仅对局部变量进行操作。顾名思义,它们只是local,并且只能在非常有限的范围内访问。因此,不可能从另一个线程访问局部变量。这意味着指令是否是原子的并不重要。

于 2015-05-15T21:48:44.580 回答
5

不是它不是,它可能会导致真正的问题。这个测试应该打印 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不能解决问题。

于 2013-03-08T05:55:29.867 回答
2

不,它不是原子的,字节码可以与其他线程交错。

于 2013-03-08T05:39:26.433 回答
0

i++ 在 java 中不是原子的。
最好使用

AtomicInteger atomic= new AtomicInteger(1);

定义了一些方法,例如

atomic.getAndDecrement();
atomic.getAndIncrement();
atomic.decrementAndGet();
atomic.incrementAndGet();

使用上述方法的任何操作都是原子的。

这个类在java.util.concurrent.atomic包下。Java1.5为线程安全和线程并发添加了许多特性。

于 2013-03-08T06:32:27.360 回答
-1

它不是原子的。这是静态 int 后增量生成的字节码:

0 getstatic 18;    // Load value of variable.
3 iconst_1;
4 iadd;
5 putstatic 18;    // Store value.
于 2014-09-27T22:06:50.487 回答