并发截图版


在这里插入图片描述
在这里插入图片描述
1.进程:操作系统分配资源(空间、文件、接口等)的基本单位
线程:CPU执行的基本单位。


2.1个cpu在一个时间点只执行一个线程。能执行多个线程是因为线程切换(上下文切换)


3.ALU:计算使用
Registers:存储
PC:记录位置
在这里插入图片描述
线程切换时要【保护现场】,下次切回来再使用。

切换线程也有线程开销的,线程个数经验:
cpu 密集型n+1 非cpu密集型 2n+1


在这里插入图片描述
重量级:操作系统来管理的;
轻量级:不需要操作系统来管理的,都是轻量级。


在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Atomic与CAS

Atomic包下为什么能保持线程安全呢?其原理是CAS。其源码调用了native方法的compareAndSwap。如下:
在这里插入图片描述
在这里插入图片描述

1.Atomic包下的自增操作流程如下:

自旋锁,乐观锁

第一步,先读到原来的m的值,如0,即读取当前值;
第二步,计算新的值,如自增1,变成1,即计算结果值;
第三步,比较取出来的值,即0,与现在m的值是否相等;
如果上述不相等,则再次循环上述三步,直到相等为止。这个一直循环的过程称为自旋锁,也是乐观锁。无限循环,什么时候成功了,什么时候为止。

什么是ABA问题

ABA就是比较取出来的值和原来的值的时候发现是相等的,但是被别的线程修改后又修改回来的,如0->3->0,虽然前后检查都是0,但是中间别修改成3又还原了。这就是ABA问题。

如何处理ABA问题

有些场合不需要处理ABA问题,如果确实要处理,就是加版本号还识别。

自旋锁一定比重量级锁效率高吗?

大多数情况是的,不完全是。自旋锁是用户空间级别的,是一直消耗CPU资源的。如果一次操作比较慢的话,消耗CPU会很多。

CAS即compareAndSwap是如何保证原子性的

在上述说的三个步骤中,比较值一致后再set,这个过程是不具备原子性的。比如,比较相等后,还有可能被其他线程修改的可能,CAS是如何保证原子性呢?
我们看源码,其调用的是cpp的UnSafe类,如下:
在这里插入图片描述
最终调用了一条CPU原句: LOCK_IF_MP(cmpxchg)
在这里插入图片描述
调用了汇编指令的cmpxchg1命令。
LOCK_IF_MP:如果是多processor则lock。 MP:Mulit Processor。

在这里插入图片描述
在这里插入图片描述
总线分3:数据总线、地址总线、控制总线。


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

对象布局

4大块:markwork、classpointer、实例数据、对齐填充。

markwork中有哪些信息

有锁标志、GC标志等。
在这里插入图片描述
在这里插入图片描述
在上述代码中,有一个普通对象和一个加锁synchronized对象,其markword信息如下:前者显示的是无锁,即普通对象,后者显示的是轻量级锁,也就是自旋锁。
在这里插入图片描述
那么,何时会变成偏向锁呢?见如下改动:
偏向锁延迟4s,大于等于4s,即会变为偏向锁。
在这里插入图片描述


偏向锁:
在这里插入图片描述

为什么会有偏向锁

根据统计,>70%的情况下,即使使用synchronized加锁,同时也只有一个线程在运行,所以就没必要加锁。偏向锁就是这么诞生的,为了优化。
第一个线程来的时候,没有锁竞争,只用偏向锁来锁定,其实就是标识了线程id;
后续线程来的时候,有了竞争,此时需要偏向锁撤销偏向锁升级为自旋锁,自旋锁还是会优先给当前线程持有。
自旋锁实现方式就是CAS,见上边有。就是竞争到后把自己的线程id标识上去。

在这里插入图片描述

在这里插入图片描述
使用synchronized的时候,现在已经不再需要调优了。JVM已经自动优化了。直接使用synchronized即可,它内部自动进行一系列锁升级。
在这里插入图片描述

启动偏向锁一定有性能提升吗

未必。见上边截图。

Java – 偏向锁、轻量级锁、自旋锁、重量级锁


关于线程使用java内存:
在这里插入图片描述
关于共享变量的规定:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可见性:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码示例:
两个线程一个写,一个读,如下。
没有关联的代码,会被重排序。
有几种情况,以下列举两种:
第一种情况:
在这里插入图片描述

第二种情况:
在这里插入图片描述
其实,上述2.1和2.2由于没有变量依赖关系,也是可以重排序的。如下:
在这里插入图片描述
在这里插入图片描述
如何才能实现线程安全性呢?见下:
在这里插入图片描述
synchronized作用:
1.锁内的代码只能一个线程执行,避免了线程的交叉执行。即锁内部代码的原子性。
2.每次只有一个线程在执行,就是as-if-serial原理,即使单线程自己重排序也是没关系的。
3.synchronized默认就能共享变量更新。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
解决办法1:加锁
在这里插入图片描述
或者改进一下减少锁粒度:
在这里插入图片描述
在这里插入图片描述
可重入锁还可以拆分很多变种,功能强大。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/answer100answer/article/details/106961796
今日推荐