Java多线程之volatile
作者:互联网
问题
Peterson算法是一个实现互斥锁的并发程序设计算法,可以控制两个线程访问一个共享的单用户资源而不发生访问冲突。
参照《现代操作系统》,用Java实现了Peterson算法。
public class Mutex {
private int turn;
private boolean[] interested = new boolean[2];
public void enterRegion(int id) {
int other = 1 - id;
interested[id] = true;
turn = id;
while (turn == id && interested[other]){
}
}
public void leaveRegion(int id) {
interested[id] = false;
}
}
测试代码如下:
public class Peterson {
public static final Mutex m = new Mutex();
public static void main(String[] args) {
call(0);
call(1);
}
public static void call(int i) {
new Thread(()->{
while (true) {
m.enterRegion(i);
System.out.print("thead "+i+" start a job............");
System.out.println("thead "+i+" finish a job");
m.leaveRegion(i);
}
}).start();
}
}
预期结果是终端交替不断的输出
thead 0 start a job............thead 0 finish a job
thead 1 start a job............thead 1 finish a job
事实是,程序陷入死锁,终停止输出内容。
原因
turn = id;
while (turn == id && interested[other]){
}
由于处理器为了提高处理速度,不直接和内存进行通讯,而是先将系统内存的数据读到内部缓存(L1,L2或其他)后再进行操作,上面代码中turn=id
在一个线程执行后,只是改变了缓存中的内容,这对另一个线程是不可见的。
当两条线程同时执行的这一语句,各自将turn修改为自己的id,而后在while循环中陷入等待。
解决办法
在声明字段turn时,使用volaite
修饰,强制要求JVM保证变量在线程工作内存和主存之间一致性。
标签:Java,int,id,turn,job,volatile,多线程,public,thead 来源: https://www.cnblogs.com/engreal/p/10542274.html