Java高并发程序-Chapter2 Java并行程序基础 (第六讲)volatile 与 Java 内存模型 JMM

 2019-12-10 16:15  阅读(1063)
文章分类:Java Core

Java内存模型都是围绕着原子性、有序性和可见性展开的

1. 原子性

指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其它线程干扰。

2. 可见性

指当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改。

显然,对于串行程序来说,可见性问题是不存在的。因为你在任何一个操作步骤中修改了某个变量,那么在后续的步骤中,读取这个变量的值,一定是修改后的新值

3. 有序性

在并发时,程序的执行可能就会出现乱序 ,需要做
指令重排,就是为了
尽量少的中断流水线

Java使用了一些特殊的操作或者关键字来申明、告诉虚拟机,在这个地方,要尤其注意,不能随意变动优化目标指令。

关键字
volatile就是“易变的,不稳定的”

当你用 volatile去申明一个变量时,就等于告诉了虚拟机,这个变量极有可能会被某些程序或者线程修改。

为了确保这个变量被修改后,应用程序范围内的所有线程都能够“看到”这个改动,虚拟机就必须采用一些特殊的手段,保证这个变量的可见性等特点

比如,根据编译器的优化规则,如果不使用 volatile申明变量,那么这个变量被修改后,其他线程可能并不会被通知到,甚至在别的线程中,看到变量的修改顺序都会是反的。但一旦使用 volatile,虚拟机就会特别小心地处理这种情况

  1. Volatile保证操作的原子性

20191210001691\_1.png

保证t操作 即使在32位系统中, 也是原子操作的。

  1. Volatile并不能代替锁,它也无法保证一些复合操作的原子性

例如:

package com.john.learn.high.concurent.ch02.volatileJmm;

    public class PlusTask {

        private volatile static int count = 0;

        public static class Plus implements Runnable {

            @Override
            public void run() {

                for (int i = 0; i < 1000; i++) {
                    count++;
                }
            }
        }

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

            Thread[] threads = new Thread[10];

            Plus plus = new Plus();

            for (int i = 0; i < threads.length; i++) {
                threads[i] = new Thread(plus);
                threads[i].start();
            }

            for (int i = 0; i < threads.length; i++) {

                threads[i].join();
            }

            System.out.println("Total count:"+PlusTask.count);
        }

    }

static int count =0;

多线程 count++ 假设 10000次 ,最终结果小于10000.

20191210001691\_2.png

3. 保证数据的可见性和有序性

public class NoVisibility {

      private static int number;

      private volatile static boolean ready;

      private static class ReaderThread extends Thread {

        @Override
        public void run() {

         while (!ready)
           ;

         System.out.println(ready);
         System.out.println(number);
        }
      }

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

        ReaderThread readerThread = new ReaderThread();
        readerThread.start();

        Thread.sleep(1000);

        number = 42;
        ready = true;

        Thread.sleep(1000);
      }

    }

在主线程修改 ready变量的状后, Reader Thread可以发现这个改动,并退出程序。

如果 private volatile static boolean ready; 去掉volatile ,程序无法退出

这个问题就是一个典型的可见性问题

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Java高并发程序-Chapter2 Java并行程序基础 (第六讲)volatile 与 Java 内存模型 JMM

相关推荐