JMM

JMM,第1张

JMM
  • 一、JMM是什么?
  • 二、volatile可见性
    • 1.代码
    • 2.加入在 int number 前面加入volatile关键字
  • 二、volatile不保证原子性
    • 1.为什么不能保证原子性呢
    • 2.如何保证原子性
    • 3.为什么能保证原子性 Atomic



提示:以下是本篇文章正文内容,下面案例可供参考

一、JMM是什么?

JMM指的是java 内存模型。
JMM的三大特性 可见性,原子性,有序性
volatile三大特性 可见性,不保证原子性,禁止指令重排

二、volatile可见性

可见性例子:如果多个线程 *** 作主线程的一个变量的值时,当一个线程 *** 作完成时,其它线程会立马得到主线程改的值

1.代码

代码如下(示例):

import java.util.concurrent.TimeUnit;

/**
 * 验证volatile的可见性
 *  1.1假如int mumber=0; number 变量没有添加volatile关键字修饰
 */

public class Test {
    public static void main(String[] args) {
        myDate myDate = new myDate();
        new Thread(()->{
           System.out.println(Thread.currentThread().getName()+"\t updated number="+myDate.number);
           //睡了8秒钟
            try {
                TimeUnit.SECONDS.sleep(8);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            myDate.bigNumber();
            System.out.println(Thread.currentThread().getName()+"\t updated number="+myDate.number);
        },"a1").start();
        while (myDate.number==0){
        }
        System.out.println("可见性触发");
    }
}
class  myDate {
  int number=0;
  public  void  bigNumber(){
      number=20;
  }
}

没有打印 可见性触发 程序一直在while 循环

2.加入在 int number 前面加入volatile关键字

代码如下(示例):

 volatile int number=0;


打印了 可见性触发 程序停止了


二、volatile不保证原子性

原子性指的是:不可分割,完整性,某个线程正在做某个具体业务时,中间不可以被加塞,需要整体完整,要么同时成功,要么同时失败

    public static void main(String[] args) {
        myDate myDate = new myDate();
        for (int i = 0; i < 20; i++) {
            new Thread(()->{
                for (int j = 0; j <1000; j++) {
                    myDate.bigNumber();
                }
            },"线程"+String.valueOf(i)).start();
        }
    //需要等待上面20个线程全部计算完成,再用main线程取得最终的结果值看是多少
        //为什么是>2默认后台有两个线程,一个是main线程,一个是gc线程
        while (Thread.activeCount()>2){
            //线程礼让
            Thread.yield();
        }
        System.out.println(Thread.currentThread().getName()+"\t finally number value=" +myDate.number);
    }
}
class  myDate {
  volatile int number=0;
  public  void  bigNumber(){
      number++;
  }
}

两次运行的结果不一样

1.为什么不能保证原子性呢

2.如何保证原子性
  1. 加上synchronized 不推荐使用大材小用
  volatile int number=0;
  public synchronized void  bigNumber(){
      number++;
  }
  1. 使用AtomicInteger 带原子的
 AtomicInteger atomicInteger= new AtomicInteger();
  
  public void addAtomic(){
      atomicInteger.getAndIncrement();
  }

然后调用方法

  for (int i = 0; i < 20; i++) {
            new Thread(()->{
                for (int j = 0; j <1000; j++) {
                    myDate.bigNumber();
                    myDate.addAtomic();
                }
            },"线程"+String.valueOf(i)).start();
        }

都可以保证原子性

3.为什么能保证原子性 Atomic

、、、

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/736293.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-04-28
下一篇2022-04-28

发表评论

登录后才能评论

评论列表(0条)

    保存