Java并发编——Java锁的实现原理

一、基础概念

多CPU:一台计算机上多个物理CPU

多核:一个CPU上多个核心

超线程技术:一个核心多个执行执行单元

二、CPU内存架构:

Java并发编——Java锁的实现原理

高度缓存L1、L2、L3:

Java并发编——Java锁的实现原理

4核8线程:

Java并发编——Java锁的实现原理

这样就存在缓存一致性问题。

解决缓存一致性问题的方法:总线锁和缓存锁

(1)总线锁

Java并发编——Java锁的实现原理

这样之后i的值都为2,但是我们期待的结果是i = 3。

那么总线锁的意思是当CPU1拿到变量处理完的时候CPU2处于阻塞状态,当CPU1处理完之后,CPU2才能进行处理。

Java并发编——Java锁的实现原理

总线锁带来的问题:存在阻塞问题,性能较低。

(2)缓存锁

缓存锁只锁定缓存的数据, 不锁定总线。

CPU1修改完i的值,写回到内存中。此时CPU2嗅探到总线上i的值与本地缓存中i的值不一致,则缓存中i的值失效,CPU2从总线锁上去取i的值,并进行运算。

缓存一致性:处理器上提供的缓存协议,保证了缓存一致性。

缓存协议MESI:

M:modify

E:execusive

S:shared

I :invalid

E:execusive状态:数据在本地缓存中,切与内存中数据一致;其他的CPU缓存中没有:

Java并发编——Java锁的实现原理

S:shared状态:每个核心的缓存都一样,且与内存一致:

Java并发编——Java锁的实现原理

M和I状态:其中一个核心修改了值,那么其他的核心的缓存失效

Java并发编——Java锁的实现原理 我刚整理了一套2018最新的0基础入门和进阶教程,无私分享,加Java学习裙 :678-241-563 即可获取,内附:开发工具和安装包,以及系统学习路线图。

三、Volatile和Synchronized

Volatile:保证共享变量的可见性

向处理器发送一条LOCK#使

1、引起处理器缓存回写到内存中

2、使其他的处理器缓存失效

Synchronized:可见性和排他性

可以修饰方法和代码块,支持重入

jdk6之前,是重量级锁

//实例锁:public class App { public synchronized void demo(String param){ synchronized (this){ //实例锁 } } public static void main(String[] args){ App app = new App(); //下面两个代码排队执行 new Thread(()->{ app.demo(Thread.currentThread().getId()+""); }).start(); new Thread(()->{ app.demo(Thread.currentThread().getId()+""); }).start(); }}123456789101112131415161718

创建两个实例就不行了:

//实例锁:public class App { public synchronized void demo(String param){ synchronized (this){ //实例锁 } } public static void main(String[] args){ App app = new App(); App app1 = new App(); //下面两个代码排队执行 new Thread(()->{ app.demo(Thread.currentThread().getId()+""); }).start(); new Thread(()->{ app1.demo(Thread.currentThread().getId()+""); }).start(); }}12345678910111213141516171819

全局锁:对所有实例都可以

//全局锁:public class App { public synchronized void demo(String param){ synchronized (App.class){ //全局锁 } } public static void main(String[] args){ App app = new App(); //下面两个代码排队执行 new Thread(()->{ app.demo(Thread.currentThread().getId()+""); }).start(); new Thread(()->{ app.demo(Thread.currentThread().getId()+""); }).start(); }}123456789101112131415161718
Java并发编——Java锁的实现原理

锁的转换:

无锁状态->偏向锁->轻量级锁->重量级锁

偏向锁:大部分情况下,多线程之间不仅仅不会存在锁竞争,而且还总是由同一个线程获得

如果多次访问的是同一个线程的话,只需要获取一次锁

Java并发编——Java锁的实现原理

Java并发编——Java锁的实现原理

猜你喜欢

转载自blog.csdn.net/qq_41212104/article/details/80629816