五个哲学家竞争五只筷子,只有同时强到两只筷子才能吃饭,吃完后释放筷子,然后思考,思考完了继续抢筷子吃饭...大致如此
public class PhilosopherEating {
private static Integer[] chopsticks = {1, 2, 3, 4, 5};
public static void main(String[] args) {
for (int i = 0; i < chopsticks.length; i++) {
new Philosopher(i).start();
}
}
static class Philosopher extends Thread {
private int order;
public Philosopher(int order) {
this.order = order;
}
@Override
public void run() {
deadLock();
// liveLock2();
}
public void liveLock2() {
while(true) {
boolean f = order % 5 < (order + 1) % 5;
if (f) {
synchronized (chopsticks[order % 5]) {
System.out.println("p" + order + ": got left chopstic");
sleepWithoutTryCatch(3000);
synchronized (chopsticks[(order + 1) % 5]) {
System.out.println("p" + order + ": got right chopstic");
System.out.println("p" + order + ": eating...");
sleepWithoutTryCatch(5000);
}
}
System.out.println("p" + order + ": thinking...");
sleepWithoutTryCatch(5000);
} else {
synchronized (chopsticks[(order + 1) % 5]) {
System.out.println("p" + order + ": got right chopstic");
sleepWithoutTryCatch(3000);
synchronized (chopsticks[order % 5]) {
System.out.println("p" + order + ": got left chopstic");
System.out.println("p" + order + ": eating...");
sleepWithoutTryCatch(5000);
}
}
System.out.println("p" + order + ": thinking...");
sleepWithoutTryCatch(5000);
}
}
}
public void liveLock1() {
while(true) {
synchronized (chopsticks) {
System.out.println("p" + order + ": got left chopstic");
sleepWithoutTryCatch(3000);
System.out.println("p" + order + ": got right chopstic");
System.out.println("p" + order + ": eating...");
sleepWithoutTryCatch(5000);
}
System.out.println("p" + order + ": thinking...");
sleepWithoutTryCatch(5000);
}
}
public void deadLock() {
while(true) {
synchronized (chopsticks[order % 5]) {
System.out.println("p" + order + ": got left chopstic");
sleepWithoutTryCatch(3000);
synchronized (chopsticks[(order + 1) % 5]) {
System.out.println("p" + order + ": got right chopstic");
System.out.println("p" + order + ": eating...");
sleepWithoutTryCatch(5000);
}
}
System.out.println("p" + order + ": thinking...");
sleepWithoutTryCatch(5000);
}
}
void sleepWithoutTryCatch(long millis) {
try {
sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static Integer[] chopsticks = {1, 2, 3, 4, 5};
把上面代码中的数组改为{1, 1, 1, 1, 1}
发现死锁没了,哲学家们一个接一个的进餐
于是有了一点猜测,又试了一次把数组改为{1, 1, 3, 4, 5}
就发现有四个哲学家同时拿到了一只筷子,紧接着有一个哲学家又拿到了一只,然后循环进餐
数组中相同的1
是同一个对象,两个线程使用synchronized
无法同时获取这个对象的锁,自然就造成了同时只有四个哲学家拿到筷子的现象
Integer i = 1;
我们这样的一段代码在javac(jdk1.5及之后)编译之时会有一个自动装箱的过程,编译后的代码相当于这样的
Integer i = Integer.valueOf(1);
为什么Integer.valueOf(1)
产生的是同一个对象,进源码看一下发现
// Integer.class
static final int low = -128;
static final int high;
static final Integer cache[];
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
// Integer.$IntegerCache.class
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
从以上源码不难发现,默认情况下在[-128~127]
区间内,Integer.valueOf(i)
返回的都是同一个对象