Java多线程中的内存可见性

刚刚看了一下synchronized和volatile的区别,这里做一下笔记。

多线程中内存是如何分配的?

分为主内存和线程内存,当线程与其他线程共享一个变量时,便会把主内存的变量复制到线程内存中去。当发生对变量的修改时,会同步到主内存,主内存再同步到其他线程内存中去。

Synchronized实现可见性

JMM对Synchronized规定:

线程加锁时,将清空线程内存中共享变量的值,从而使用共享变量时从主内存中重新读取新值。

线程解锁前,必须把共享变量的最新值刷新到主内存中。

线程执行互斥代码过程:

1、 获得互斥锁

2、 清空线程内存

3、 从主内存中拷贝最新副本到线程内存

4、 执行代码

5、 将更改后的变量刷新到主内存

6、 释放互斥锁

指令重排序:代码书写的顺序和实际执行的顺序不同,目的是提高程序的性能。

编译器优化重排序:编译器重新排序

指令级并行优化从排序:CPU并行执行时优化

内存系统从排序:读写缓存的优化

as-if-serial:无论如何重排序,程序执行的结果都应该与代码顺序执行的结果一致。

java编译器保证as-if-serial,但是在多线程程序中并不能保证顺序执行。

Volatile实现可见性

加入内存屏障和禁止重排序优化来实现,会在volatile写操作后加入store屏障指令,读操作前加入load屏障指令。

Volatile不能保证变量操作的原子性

Lock实现可见性

1
2
3
4
5
6
7
8
9
10
Lock lock = new ReentrantLock();
lock.lock();
try{
}finally{
         lock.unlock();
}