Java并发编程(一)Java锁的实现原理

一、基础概念

多CPU:一台计算机上多个物理CPU
多核:一个CPU上多个核心
超线程技术:一个核心多个执行执行单元

二、CPU内存架构:

这里写图片描述
高度缓存L1、L2、L3:
这里写图片描述
4核8线程:
这里写图片描述
这样就存在缓存一致性问题。
解决缓存一致性问题的方法:总线锁和缓存锁
(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状态:每个核心的缓存都一样,且与内存一致:
592818827
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();
    }
}

创建两个实例就不行了:

//实例锁:
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();
    }
}

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

//全局锁:
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();
    }
}

这里写图片描述
锁的转换:
无锁状态->偏向锁->轻量级锁->重量级锁
偏向锁:大部分情况下,多线程之间不仅仅不会存在锁竞争,而且还总是由同一个线程获得
如果多次访问的是同一个线程的话,只需要获取一次锁
这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41835916/article/details/80601373