synchronized关键字结合包装类、String使用时注意:
-
包装类:因为包装类内部缓存了部分对象,如Integer默认缓存了-128到127之间的Integer对象,使用synchronized锁定Integer时候可能会产生非预期的同步;比如线程1、2同时使用了如下代码段,就会产生意想不到的同步;
Runnable r = new Runnable() { @Override public void run() { Integer i = 1; synchronized (i) { for(int j = 0;j < 3;++j) { System.out.println(Thread.currentThread().getName()); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; Thread t1 = new Thread(r); Thread t2 = new Thread(r); t1.start(); t2.start();
虽然代码中Integer是临时变量,因为缓存的原因,其实线程1的i和线程2的i指向了同一个对象;其他
String 则是因为字符串去重的原因,不同的String内容相同时候可能会引用同一个对象,导致产生非预期的同步;
所以synchronized关键字结合 包装类、String类使用时候要非常小心,不仅如此,即便是自行编写的类,可能会返回同一个实例的场景都要辨别情况是否与业务需求一致;