JMM理解,多线程讲解,volita

JMM

java内存模型,这不是jvm

有cas的思想,每个线程搞一手副本,自己在副本修改,联系就是主存。

并发编程三个特性:

  • 可见性

  • 原子性

  • 顺序性

先简单了解:

可见性:

A改了共享变量, B知道A改了,并把自己工作内存更新了(Volatile),或是A整个流程锁起来,B才能开始执行(lock),这就叫可见。就是可见别人的修改。

原子性:

也就是一组操作要末全做,要末不做,就是事务的原子性,就是线程的业务代码的原子性。(num++是一组操作,临时变量,操作栈,下篇博客了解)。

顺序性:指令重排

什么是 指令重排:你写的程序,计算机并不是按照你写的那样去执行的。
源代码–>编译器优化的重排–> 指令并行也可能会重排–> 内存系统也会重排—> 执行
处理器在进行指令重排的时候,考虑:数据之间的依赖性!也就是单线程没问题,但是多线程之间可能会互相依赖,不可重排。
在这里插入图片描述
下面是内存交互操作有8种,虚拟机实现必须保证每一个操作都是原子的,不可在分的(对于double和long类 型的变量来说,load、store、read和write操作在某些平台上允许例外)

概述:

  • 1.就是主内存read到临时变量,临时变量load进线程的工作去内存

  • 2。线程就会use工作内存的数据(线程里的操作保证原子性),处理后align回工作内存

  • 3.工作内存store到临时变量,临时变量write回主内存
    在这里插入图片描述

Volatile 保证了可见性和顺序性,不保证原子性

可见性

问题:

主存:num=0

A改了共享变量num++;1

B不知道,num++;1

B不知道A改了,因为主存改了,B不知道,还是操作自己的工作区内存,这就叫不可见。

解决:

  • 1。在最开始时jmm为了实现并发安全,就lock整个流程,注意lock是共享标量被多线程操作时,很浪费,就像同步了。

  • 2.1 Volatile就不一样,他先是通过cpu总线嗅探来监视有没有人修改共享变量,有,就把工作取数据失效重新获取

  • 2.2 这其实还不i行啊,在传到总线时,B就会嗅探到,但还没从总线写回主内存,B就失效获取的主内存还是原来的,所以Volatile也加了锁,就是锁总线到写入主内存,不许B访问

  • 这区别就是Volatile的锁的粒度小多了

顺序性

就是java优化的啊

源代码–>编译器优化的重排–> 指令并行也可能会重排–> 内存系统也会重排—> 执行

在单线程没啥,但是多线程就不行了,会有出乎意料的,貌似违背语句从上向下执行的原则,其实是指令重排,

Volatile有内存屏障。作用:
1、保证特定的操作的执行顺序!就是有依赖的操作有序

2、可以保证某些变量的内存可见性 (利用这些特性volatile实现了可见性)

在这里插入图片描述

原子性

为啥内原子性:

  • A在修改的时候,就是正在修改,还没asgin回工作内存

  • B已经改了,并且回写到主内存,

  • A刚好运行完**,写回工作内存**,突然嗅探到改变,工作内存失效,重新加载主内存,A做的修改被覆盖了

现在看来底层的问题解决了,线程的实际业务操作还没控制,我们可以操作一手原子类 AtomicInteger 啥的,就是保证原子类对象是原子操作.

那比如

 private volatile static AtomicInteger num = new AtomicInteger();
 num.getAndIncrement();

getAndIncrement();这是原子类的方法,不是sigalnized锁,底层用的unseafe类,操作的this,offet偏移量,内存地址式的修改,比较高效,还用到了自旋锁。还用到了CAS。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值