• Volatile


    (一) Volatile是什么

      Volatile 是Java虚拟机提供的轻量级的同步机制

    1. 保证可见性
    2. 不保证原子性
    3. 禁止指令重排

     (二) JMM (Java内存模型 Java Memory Model)

      是一种抽象概念,并不保证可见性,原子性,有序性

      JMM关于同步的规定

    1. 线程解锁前,必须把共享变量的值刷新回内存
    2. 线程加锁前,必须读取主内存的最新值到自己的工作内存(自己线程私有数据区域)
    3. 加锁解锁是同一把锁

      Java 内存模型中规定所有的变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问

      但是线程对变量的操作必须在工作内存中进行,首先要将变量从主内存拷贝到自己的工作内存空间

      然后对变量进行操作,操作完成后再将变量写回主内存

      


     (三) Volatile 保证可见性 代码示例

      Volatile可见性:及时通知其他线程,主物理内存的值已经被改变

      不加Volatile

     1 package com.Interview.study.thread;
     2 import java.util.concurrent.TimeUnit;
     3 class MyData{
     4     int number = 0;
     5     public void addT060(){
     6         this.number = 60;
     7     }
     8 }
     9 
    10 public class VolatileDemo {
    11 
    12     public static void main(String[] args) {
    13         MyData myData = new MyData();
    14         new Thread(() -> {
    15             System.out.println(Thread.currentThread().getName() + "	 come in ");
    16             try {
    17                 TimeUnit.SECONDS.sleep(3);
    18             }catch (InterruptedException e){
    19                 e.printStackTrace();
    20             }
    21             myData.addT060();
    22             System.out.println(Thread.currentThread().getName() + "	 updated number value:" + myData.number);
    23         },"AAA").start();
    24 
    25         while (myData.number == 0){
    26 
    27         }
    28 
    29         System.out.println(Thread.currentThread().getName() + "	 mission is over ");
    30     }
    31 }

      运行结果

      

        加Volatile

     1 package com.Interview.study.thread;
     2 import java.util.concurrent.TimeUnit;
     3 class MyData{
     4     volatile int number = 0;
     5     public void addT060(){
     6         this.number = 60;
     7     }
     8 }
     9 
    10 public class VolatileDemo {
    11 
    12     public static void main(String[] args) {
    13         MyData myData = new MyData();
    14         new Thread(() -> {
    15             System.out.println(Thread.currentThread().getName() + "	 come in ");
    16             try {
    17                 TimeUnit.SECONDS.sleep(3);
    18             }catch (InterruptedException e){
    19                 e.printStackTrace();
    20             }
    21             myData.addT060();
    22             System.out.println(Thread.currentThread().getName() + "	 updated number value:" + myData.number);
    23         },"AAA").start();
    24 
    25         while (myData.number == 0){
    26 
    27         }
    28 
    29         System.out.println(Thread.currentThread().getName() + "	 mission is over ");
    30     }
    31 }

      运行结果

      


     (四) Volatile 不保证原子性 代码示例

     1 package com.Interview.study.thread;
     2 import java.util.concurrent.TimeUnit;
     3 class MyData{
     4     volatile int number = 0;
     5     public void addT060(){
     6         this.number = 60;
     7     }
     8 
     9     public  void addNumber(){
    10         number++;
    11     }
    12 }
    13 
    14 public class VolatileDemo {
    15 
    16     public static void main(String[] args) {
    17         MyData myData = new MyData();
    18 
    19         for(int i = 0 ; i < 20 ; i++){
    20             new Thread(() -> {
    21                 for(int j = 0 ;j < 1000 ; j++){
    22                     myData.addNumber();
    23                 }
    24             },String.valueOf(i)).start();
    25         }
    26 
    27         while (Thread.activeCount() > 2){
    28             Thread.yield();
    29         }
    30         System.out.println(Thread.currentThread().getName() + "	 finally number value " + myData.number);
    31     }
    32 }

    代码起了20个线程对其进行++ 1000次 

    预期结果应该是20000  但是执行结果有丢失 

    不保证原子性


     (五)指令重排

       

      多线程环境中线程交替执行,由于编译器优化重排的存在

       两个线程中使用的变量能否保证一致性是无法确定的,结果无法预测


         细雨

  • 相关阅读:
    Dictionary<string, object>不区分大小写
    修改Windows远程桌面端口
    LookupError: unknown encoding: cp65001的问题
    Git命令基本操作备忘
    MariaDB10 修改默认密码
    android去除标题栏
    解决Eclipse中Android SDK Manager图标不见了的问题
    HTML邮件注意事项
    不同内核浏览器的差异以及浏览器渲染简介(转)
    DIV+CSS两种盒子模型
  • 原文地址:https://www.cnblogs.com/misscai/p/12708167.html
Copyright © 2020-2023  润新知