Peterson算法是一个实现互斥锁的并发程序设计算法,能够控制两个线程访问一个共享的单用户资源而不发生访问冲突。 参照《现代操做系统》,用Java实现了Peterson算法。java
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保证变量在线程工做内存和主存之间一致性。spa