一、基础概念
多CPU:一台计算机上多个物理CPU
多核:一个CPU上多个核心
超线程技术:一个核心多个执行执行单元
二、CPU内存架构:
高度缓存L1、L2、L3:
4核8线程:
我刚整理了一套2018最新的0基础入门和进阶教程,无私分享,加Java学习裙 :678-241-563 即可获取,内附:开发工具和安装包,以及系统学习路线图
这样就存在缓存一致性问题。
解决缓存一致性问题的方法:总线锁和缓存锁
(1)总线锁
这样之后i的值都为2,但是我们期待的结果是i = 3。
那么总线锁的意思是当CPU1拿到变量处理完的时候CPU2处于阻塞状态,当CPU1处理完之后,CPU2才能进行处理。
总线锁带来的问题:存在阻塞问题,性能较低。
(2)缓存锁
缓存锁只锁定缓存的数据, 不锁定总线。
CPU1修改完i的值,写回到内存中。此时CPU2嗅探到总线上i的值与本地缓存中i的值不一致,则缓存中i的值失效,CPU2从总线锁上去取i的值,并进行运算。
缓存一致性:处理器上提供的缓存协议,保证了缓存一致性。
缓存协议MESI:
M:modify
E:execusive
S:shared
I :invalid
E:execusive状态:数据在本地缓存中,切与内存中数据一致;其他的CPU缓存中没有:
S:shared状态:每个核心的缓存都一样,且与内存一致:
M和I状态:其中一个核心修改了值,那么其他的核心的缓存失效
三、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
锁的转换:
无锁状态->偏向锁->轻量级锁->重量级锁
偏向锁:大部分情况下,多线程之间不仅仅不会存在锁竞争,而且还总是由同一个线程获得
如果多次访问的是同一个线程的话,只需要获取一次锁
网友评论