快捷搜索:  汽车  科技

integer可以做返回类型吗(你竟然用Integer作为synchronized的锁对象)

integer可以做返回类型吗(你竟然用Integer作为synchronized的锁对象)这样一来,synchronized(integer)原因就知道了, integer 是创建了一个新的Integer对象,并将引用赋值给integer。因为integer一直在变,线程每次加锁可能都加在了不同对象的实例上,导致临界区控制出现问题。在上面的135显然不在范围,则返回的是新对象,又由于==是比较内存地址,所以上述会出现false。如果要比较包装类是否相等,正确的做法是equals方法,Integer也重写了equals,判断内部基本数据类型是否一样。那在说Integer,不少人可能会见过这样的题。Integer i1 =125; Integer i2 =125; System.out.println(i1==i2); Integer i3 =135; Integer i4 =135; System.out.println(i3==i4); 答案是true,false,这样的结果

integer可以做返回类型吗(你竟然用Integer作为synchronized的锁对象)(1)

推荐阅读:我凭借这份pdf拿下了蚂蚁金服、字节跳动、小米等大厂的offer

在使用多线程编程时,往往会使用一些手段保证线程安全,也就是加锁,但是加锁也必须合理,如使用synchronized对对象加锁时,如果不注意,还可能发生错误的加锁。

先看一段小测试,在这个小测试中,启动了1000个线程,每个线程在对integer加1前都先获得Integer的锁,这看似是线程安全的,并且预期可能会得到1000这个值,而然并不然,在运行多次之后他总是输出<=1000的值,那么,这犊子是哪出问题了。

static Integer integer =new Integer("0"); static CountDownLatch mCountDownLatch =new CountDownLatch(1000); public static void main(String[] args) throws InterruptedException { for (int i = 1; i <=1000; i ) { new Thread(()->{ synchronized (integer){ integer ; mCountDownLatch.countDown(); } }).start(); } mCountDownLatch.await(); System.out.println(integer); }

这其实就是上述所说:"错误的加锁对象",也就是Integer作为锁对象这是个不正确的选择。

那在说Integer,不少人可能会见过这样的题。

Integer i1 =125; Integer i2 =125; System.out.println(i1==i2); Integer i3 =135; Integer i4 =135; System.out.println(i3==i4);

答案是true,false,这样的结果是由Integer的缓存导致,在直接对Integer=xxx时候,其实调用了Integer.valueOf,(可以使用javap命令反编译查看)

integer可以做返回类型吗(你竟然用Integer作为synchronized的锁对象)(2)

而Integer.valueOf中,如果参数值在一定范围内,就从IntegerCache缓存中返回,也就是说在一定范围内多个相同的值是同一个对象,超出的话则return new Integer(i)返回一个新的Integer。而这个范围在-128-127,

integer可以做返回类型吗(你竟然用Integer作为synchronized的锁对象)(3)

在上面的135显然不在范围,则返回的是新对象,又由于==是比较内存地址,所以上述会出现false。如果要比较包装类是否相等,正确的做法是equals方法,Integer也重写了equals,判断内部基本数据类型是否一样。

integer可以做返回类型吗(你竟然用Integer作为synchronized的锁对象)(4)

这样一来,synchronized(integer)原因就知道了, integer 是创建了一个新的Integer对象,并将引用赋值给integer。因为integer一直在变,线程每次加锁可能都加在了不同对象的实例上,导致临界区控制出现问题。

解决办法也很容易,只要加在一个不变的对象上即可。

static Integer integer =new Integer("0"); static CountDownLatch mCountDownLatch =new CountDownLatch(1000); static Object sObject= new Object(); public static void main(String[] args) throws InterruptedException { for (int i = 1; i <=1000; i ) { new Thread(()->{ synchronized (sObject){ integer ; mCountDownLatch.countDown(); } }).start(); } mCountDownLatch.await(); System.out.println(integer); }

(不只Integer,Character、Short、Long也有缓存,但是Float和Double却没有)

关注我,后续更多干货奉上!

猜您喜欢: