Integer String 对象作为锁的注意事项
Integer vs int
由一个多线程共享Integer类变量问题引起的。。。
中,解释了为什么锁不住Integer对象,本次我们做一些实践
import java.util.Date; /** * https://www.cnblogs.com/silyvin/p/11475233.html * Created by sunyuming on 19/8/28. */ public class MultiLock { public Integer lockInteger; public String lockString; public String lockStringNew; public static void main(String [] f) throws InterruptedException { MultiLock a = new MultiLock(); MultiLock b = new MultiLock(); a.lockInteger = 127; b.lockInteger = 127; a.lockString = "abc"; b.lockString = "abc"; a.lockStringNew = new String("abc"); b.lockStringNew = new String("abc"); System.out.println("\n当127自动装箱Integer时"); new Thread(new MyThreadInteger(a)).start(); new Thread(new MyThreadInteger(b)).start(); Thread.sleep(10000); a.lockInteger = 128; b.lockInteger = 128; System.out.println("\n当128自动装箱Integer时"); new Thread(new MyThreadInteger(a)).start(); new Thread(new MyThreadInteger(b)).start(); Thread.sleep(10000); a.lockInteger = new Integer(127); b.lockInteger = new Integer(127); System.out.println("\n当Integer堆时"); new Thread(new MyThreadInteger(a)).start(); new Thread(new MyThreadInteger(b)).start(); Thread.sleep(10000); System.out.println("\n当String常量池装箱时"); new Thread(new MyThreadString(a)).start(); new Thread(new MyThreadString(b)).start(); Thread.sleep(10000); System.out.println("\n当String堆时"); new Thread(new MyThreadStringNew(a)).start(); new Thread(new MyThreadStringNew(b)).start(); Thread.sleep(10000); System.out.println("\n当String堆intern时"); new Thread(new MyThreadStringNewIntern(a)).start(); new Thread(new MyThreadStringNewIntern(b)).start(); } public void testIntegerLock() { System.out.println("testIntegerLock" + System.identityHashCode(lockInteger)); synchronized (lockInteger) { try { System.out.println("starttestIntegerLock" + new Date()); Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } } public void testStringLock() { System.out.println("testStringLock" + System.identityHashCode(lockString)); synchronized (lockString) { try { System.out.println("starttestStringLock"+ new Date()); Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } } public void testStringNewLock() { System.out.println("testStringNewLock" + System.identityHashCode(lockStringNew)); synchronized (lockStringNew) { try { System.out.println("starttestStringNewLock"+ new Date()); Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } } public void testStringNewInternLock() { System.out.println("testStringNewInternLock" + System.identityHashCode(lockStringNew.intern())); synchronized (lockStringNew.intern()) { try { System.out.println("starttestStringNewInternLock"+ new Date()); Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } } public static class MyThreadInteger implements Runnable { private MultiLock multiLock; public MyThreadInteger(MultiLock multiLock) { this.multiLock = multiLock; } @Override public void run() { this.multiLock.testIntegerLock(); } } public static class MyThreadString implements Runnable { private MultiLock multiLock; public MyThreadString(MultiLock multiLock) { this.multiLock = multiLock; } @Override public void run() { this.multiLock.testStringLock(); } } public static class MyThreadStringNew implements Runnable { private MultiLock multiLock; public MyThreadStringNew(MultiLock multiLock) { this.multiLock = multiLock; } @Override public void run() { this.multiLock.testStringNewLock(); } } public static class MyThreadStringNewIntern implements Runnable { private MultiLock multiLock; public MyThreadStringNewIntern(MultiLock multiLock) { this.multiLock = multiLock; } @Override public void run() { this.multiLock.testStringNewInternLock(); } } }
当127自动装箱Integer时
testIntegerLock1842818263
testIntegerLock1842818263
starttestIntegerLockWed Dec 11 11:52:04 CST 2019
starttestIntegerLockWed Dec 11 11:52:09 CST 2019
当128自动装箱Integer时
testIntegerLock2025391892
testIntegerLock755079750
starttestIntegerLockWed Dec 11 11:52:14 CST 2019
starttestIntegerLockWed Dec 11 11:52:14 CST 2019
当Integer堆时
testIntegerLock455290755
testIntegerLock2078391126
starttestIntegerLockWed Dec 11 11:52:24 CST 2019
starttestIntegerLockWed Dec 11 11:52:24 CST 2019
当String常量池装箱时
testStringLock440496836
starttestStringLockWed Dec 11 11:52:34 CST 2019
testStringLock440496836
starttestStringLockWed Dec 11 11:52:39 CST 2019
当String堆时
testStringNewLock835411425
testStringNewLock872854004
starttestStringNewLockWed Dec 11 11:52:44 CST 2019
starttestStringNewLockWed Dec 11 11:52:44 CST 2019
当String堆intern时
testStringNewInternLock440496836
testStringNewInternLock440496836
starttestStringNewInternLockWed Dec 11 11:52:54 CST 2019
starttestStringNewInternLockWed Dec 11 11:52:59 CST 2019
Process finished with exit code 0
装箱过程是通过调用包装器的valueOf方法实现的,而拆箱过程是通过调用包装器的 xxxValue方法实现的。
在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。
a+b,会先各自调用intValue方法,得到了加法运算后的数值之后,便调用Integer.valueOf方法
https://www.cnblogs.com/dolphin0520/p/3780005.html