可见性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package com.redisc;
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "c.Run") public class Run {
static boolean run = true;
public static void main(String[] args) throws Exception { new Thread(() -> { while (run) {
} }).start();
Thread.sleep(1000); run = false; }
}
|
这段代码在运行的时候,并不会跳出循环。
最开始的时候,t
线程从主内存中读取 run
的值,由于多时间内多次读取,所以 JIT
编译器,会将 run
值缓存到自己的工作内存中的高速缓存中,减少对主存中的 run
的访问,即便是,后来 run
的值被改变了,但是,还是从缓存中读取。「ps:不过,这个说法貌似有点不对,以后查证后我再完善。」
可见性解决 volatile
被 volatile 修饰的变量,不能从高速缓存中读取值。
可以修饰
1
| volatile static boolean run = true;
|
使用 synchronized 解决
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package com.redisc;
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "c.Run") public class Run {
static boolean run = true;
public static void main(String[] args) throws Exception { new Thread(() -> { while (true) { if (!run) { break; } } }).start();
Thread.sleep(1000); run = false; }
}
|
使用 synchronized
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package com.redisc;
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "c.Run") public class Run {
static boolean run = true; final static Object lock = new Object();
public static void main(String[] args) throws Exception { new Thread(() -> { while (true) { synchronized (lock) { if (!run) { break; } } } }).start();
Thread.sleep(1000); synchronized (lock) { run = false; } }
}
|
这是因为 synchronized
每次加锁前都会清除工作内存,然后重新在主内存中拷贝最新的变量副本到工作内存,执行代码,将修改后的共享变量值刷新到主内存中,释放锁。