synchronized锁对象为包装类型(修饰变量)
synchronized锁对象为包装类型时,需要考虑包装类型的缓存,如Integer默认缓存-127~128之间的数值,所以下例中锁a和锁b实际锁的是同一个对象;另外其它包装类也需要注意类似问题(如Byte/Short);
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
public static Short valueOf(short s) {
final int offset = 128;
int sAsInt = s;
if (sAsInt >= -128 && sAsInt <= 127) { // must cache
return ShortCache.cache[sAsInt + offset];
}
return new Short(s);
}
public class ConcurrentTest {
private Integer a = 100;
private Integer b = 100;
public static void main(String[] args) throws InterruptedException {
ConcurrentTest test = new ConcurrentTest();
test.testA();
test.testB();
System.err.println("a:"+ test.a);
System.err.println("b:"+ test.b);
}
private void testA() {
new Thread(() -> {
System.err.println("A thread started");
synchronized (a) {
for (int i = 0; i < 10; i++) {
System.err.println("a =>");
sleep(1);
}
}
}).start();
}
private void testB() {
new Thread(() -> {
System.err.println("B thread started");
synchronized (b){
for (int i = 0; i < 10; i++) {
System.err.println("b =>");
sleep(1);
}
}
}).start();
}
}
out==> //实际输出是等打印完a才打印b
A thread started
a =>
B thread started
a =>
a =>
a =>
a =>
a =>
a =>
a =>
a =>
a =>
b =>
b =>
b =>
b =>
b =>
当然实际开发过程中一般也不会使用包装类做锁对象!