最近在工作中和一个同事因为自增是不是原子性操作争论的面红耳赤,那Java的自增操作到底是不是原子性操作呢,答案是否的,即Java的自增操作不是原子性操作。
1、首先我们先看看Bruce Eckel是怎么说的:
In the JVM an increment is not atomic and involves both a read and a write. (via the latest Java Performance Tuning Newsletter)
意思很简单,就是说在jvm中自增不是原子性操作,它包含一个读操作和一个写操作。
2、以上可能还不能让你信服,要想让人心服口服,就必须用代码说话。正如FaceBook的文化一样:代码赢得争论。那我们就看一段代码:
以下的代码是用100个线程同时执行自增操作,每个线程自增100次,如果自增操作是原子性操作的话,那么执行完amount的值为10,000。运行代码之后,你会发现amount的值小于10,000,这就说明自增操作不是原子性的
-
-
-
-
- public class MultiThread implements Runnable {
- private int count;
- private int amount = 1;
-
- public MultiThread() {
- count = 100;
- }
-
- public MultiThread(int count) {
- this.count = count;
- }
-
- @Override
- public void run() {
- for (int i = 0; i < count; i++) {
- amount++;
- }
- }
-
- public static void main(String[] args) {
- ExecutorService executorService = Executors.newCachedThreadPool();
- MultiThread multiThread =new MultiThread();
- for (int i = 0; i < 100; i++) {
- executorService.execute(multiThread);
- }
- executorService.shutdown();
-
- try {
- Thread.sleep(60000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(multiThread.amount);
- }
- }
|
3、如果以上还不能让你信服的话,也没关系。我们就把自增操作反编译出来,看看java字节码是怎么操作的
以下是一个简单的自增操作代码
- public class Increment {
- private int id = 0;
- public void getNext(){
- id++;
- }
- }
|