Java的挥发性,同步,原子例如

您好我正在读Java并发在实践中,我读有趣的说法指出,Java的挥发性,同步,原子例如

锁定既能保证可见性和原子;易变的 变量只能保证能见度。

任何一个可以请解释,如果变量声明为挥发性所有其他线程读取更新获得价值那就是为什么我关心像声明中的原子:counter = counter + 1;

在此先感谢。

回答:

volatile关键字的效果大约是每个单独的读或写操作在该变量是原子的。但是,值得注意的是,需要多个读/写操作的操作 - 例如i ++,相当于i = i + 1,它执行一次读取和一次写入 - 不是原子的,因为另一个线程可能会在读和写之间写入i。

的原子类,像的AtomicInteger和的AtomicReference,提供更广泛的各种操作的原子,具体包括增量的AtomicInteger。

这就是为什么你需要关心的原子像反陈述=计数器+ 1

请查看这篇文章Volatile Vs Atomic

回答:

以下是一个演示这一动荡对自己是不是一个自包含例如可执行应用程序足够。四个线程每次增加一个计数器10,000次,所以你最终预计该计数器为40,000。它使用一个原始的int变量和一个AtomicInt,并且每次尝试5次这个练习。

import java.util.Collections; 

import java.util.concurrent.*;

import java.util.concurrent.atomic.AtomicInteger;

class AtomicDemo {

interface Demo extends Callable<Void> {

int getCounter();

}

static class UsePrimitive implements Demo {

private volatile int counter = 0;

public Void call() throws Exception {

for (int i = 1; i <= 10000; ++i) {

++counter;

}

return null;

}

public int getCounter() {

return counter;

}

}

static class UseAtomic implements Demo {

final AtomicInteger counter = new AtomicInteger(0);

public Void call() throws Exception {

for (int i = 1; i <= 10000; ++i) {

counter.incrementAndGet();

System.out.print("");

}

return null;

}

public int getCounter() {

return counter.get();

}

}

public static void main(String[] args) throws Exception {

ExecutorService exec = Executors.newFixedThreadPool(4);

for (int i = 1; i <= 5; ++i) {

Demo demo = new UsePrimitive();

exec.invokeAll(Collections.nCopies(4, demo));

System.out.println("Count to 40000 using primitive, attempt number " + i + ": " + demo.getCounter());

}

for (int i = 1; i <= 5; ++i) {

Demo demo = new UseAtomic();

exec.invokeAll(Collections.nCopies(4, demo));

System.out.println("Count to 40000 using atomic, attempt number " + i + ": " + demo.getCounter());

}

exec.shutdownNow();

}

}

典型输出:

Count to 40000 using primitive, attempt number 1: 39711 

Count to 40000 using primitive, attempt number 2: 39686

Count to 40000 using primitive, attempt number 3: 39972

Count to 40000 using primitive, attempt number 4: 39840

Count to 40000 using primitive, attempt number 5: 39865

Count to 40000 using atomic, attempt number 1: 40000

Count to 40000 using atomic, attempt number 2: 40000

Count to 40000 using atomic, attempt number 3: 40000

Count to 40000 using atomic, attempt number 4: 40000

Count to 40000 using atomic, attempt number 5: 40000

你看,只有AtomicInt你总是得到预期的结果。

以上是 Java的挥发性,同步,原子例如 的全部内容, 来源链接: utcz.com/qa/262331.html

回到顶部