【JUC】并发编程的艺术笔记

1.单核处理器也支持多线程执行代码,使用CPU分配时间片来实现。

2.上下文切换:任务从保存到再加载的过程。

3.减少上下文切换(避免频繁切换任务):

1)无锁并发编程。

2)CAS算法。

3)使用最少线程,避免创建不需要的线程。

4)使用协程:单线程里实现多任务的调度。

4.volatile轻量级的synchronized,保证了共享变量的可见性。

5.线程在将volatile共享变量写回共享内存时,会有lock指令,通过MESI总线嗅探机制,每个线程嗅探总线上的变量根据缓存一致性协议,使他们工作空间的变量无效,必须重新去共享内存再一个取。

6.volatile优化:将变量填充字节码到64字节,处理器的cache高速缓存行都是64字节,使用linkedTransferQueue定义了头节点和尾结点用来放置和拿取,填充字节码到64之后保证头尾结点 不会被同一高速缓存行锁定。

7.sychronized重量级锁,使用方法:

1)锁普通同步方法,锁当前实例对象

2)锁静态同步方法,锁当前类的Class对象。

3)同步方法块,锁括号里指定的对象。

8.JVM基于进入和退出Monitor对象来实现同步,字节码monitorexit和monitorenter指令 是sychronized底层实现,字节码底层是操作系统的mutexLock互斥锁,因为Java的线程模型是和OS一一对映的,所以每次mutexLock都要引起 用户态内核态的切换 。每一个对象都有自己的监视器。

9.Java的对象头(1,Mark Word 2,指向类的指针 3,数组长度(只有数组对象才有))

mark word无锁条件下存储:hashcode 分代年龄 锁标记位。

mark word对应锁的状态变化

 

 

10.对象的结构(对象头 对象实例 填充字段)

11.无锁:两种情况:不存在资源竞争,存在竞争但是只允许一个线程修改(CAS)实现无锁编程

12.偏向锁:使用mark word来标识线程ID。

运行过程中,同步锁只有一个线程访问,不存在多线程争用的情况,则线程是不需要触发同步的,这种情况下,就会给线程加一个偏向锁。

如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会消除它身上的偏向锁,将锁恢复到标准的轻量级锁。

13.轻量级锁:

 

 

1)其他线程竞争对象,会自旋(CPU轮询访问是否解锁了)。

2)适应性自旋:根据上一个在锁上的自旋和锁状态 确定自旋时间。

3)外面竞争的资源超过1个,升级为重量级锁。

14.锁只能升级 不能降级。

15.处理器保持原子操作:通过缓存、通过总线加锁。

16.Java使用锁、循环CAS来保证原子性。

17.CAS比较与替换,CAS使用处理器层面的指令完成原子操作。

cas以及ABA问题:https://www.cnblogs.com/cckong/p/14444374.html

18.悲观锁:操作系统认为如果不严格同步线程调用,就一定会出异常。所以只提供一个线程调用,而阻塞其他线程。

乐观锁:操作系统认为不会被其他线程更改,所以不需要加锁。、

19.运行Java程序时,启动一个Java进程,在进程中有很多线程比如用户线程main、守护线程gc等。

20.设置线程优先级,但是具体还是要由操作系统决定。

 

 21.线程状态以及变化过程

 

 

22.守护线程,守护线程的run方法代码块里不一定全部执行,因为JVM可能比执行更早退出。

 

23.线程的中断机制:

1)interrupt():设置中断标识位,正在运行的线程无法中断,在wait、sleep、jion的线程终止阻塞,抛出异常。

2)isInterrupted():方法唯一的作用只是测试线程是否已经中断,中断标识位的状态并不受到该方法的影响。

3)interrupted():方法的作用是测试当前线程是否已经中断,线程的中断标识位由该方法清除。

24.sychronized竞争资源图

 

 25.sychronized加等待/通知机制的流程图

wait/notify必须是同步块、同步方法里面的。

调用wait方法,进入等待队列,状态也变为等待状态。

调用notify方法,并不会马上放弃锁,要等运行完,才释放。

notify是让一个线程从等待队列到同步队列,nitufyAll是让所以线程从等待队列到同步队列。

同步队列上的线程状态为Blocked阻塞态。

 

 26.jion方法 让调用此方法的线程 插队执行。

 

 27.ThreadLocal 线程变量,以ThreadLocal对象为键,任意对象为值得储存结构(ThreadLocalMap类型)。

应用:spring使用threadLocal保证单个线程中得数据库连接是同一个。

28.锁 lock  提供了比synchronized更加灵活的加锁方式

 

 

29.AQS队列同步器:构建锁以及其他同步组件的基础框架。同步器可以独占式也可以共享式获得同步状态。

使用int变量来表示同步状态,以及内置的FIFO队列来完成线程的排队。

重写同步器方法时需要用到 下面来访问、改变同步状态

getState();//获得同步状态
setState(int newStare);//设置当前同步状态
compareAndSet(int expect,int update);//CAS设置当前状态

 

posted @ 2021-04-05 20:29  枫叶像思念  阅读(80)  评论(0编辑  收藏  举报