大家好,欢迎来到IT知识分享网。
今天同事写了一段代码,并且郁闷了一天,看看他的代码(代码做了抽象)。
public class Example { private Integer lock = new Integer(0); private int count = 0; public void increment() { synchronized (lock) { count++; } } public int getCount() { synchronized (lock) { return count; } } }
大家看出问题来了吗?这是个不小心会犯错的场景,代码中 lock 锁并没有生效(锁范围扩大,出现了死锁)!
正确的代码应该是这样的:
public class Example { private Object lock = new Object(); private int count = 0; public void increment() { synchronized (lock) { count++; } } public int getCount() { synchronized (lock) { return count; } } }
原因
在Java中,锁是基于对象的,它们控制对于同一对象的并发访问。每个对象都有一个唯一的对象标识符(Object Identifier),也就是对象的内存地址。在多线程环境中,锁起着非常重要的作用,它们确保了线程间的同步性。
然而,Integer是一个不可变的对象,它的值一旦被设置就无法更改。在Java中,对于不可变对象的操作会创建一个新的对象,因为原始对象本身不能被修改。因此,每次对Integer对象进行操作,都会创建一个新的对象。
如果使用一个Integer对象作为锁对象,那么当多个线程试图获取该锁时,实际上它们获取的是不同的对象。也就是说,它们各自锁定的是不同的内存地址,而不是同一个内存地址。这会导致多个线程同时访问共享资源的情况发生,从而可能导致线程安全问题的发生。
为了避免这种情况,应该使用一个可变的对象,比如一个专门为了锁而创建的空的Object对象。这样所有的线程都可以锁定同一个对象,从而达到同步的效果。
最后,为了避免其他人犯同样的错误,立刻把这条规则写入了编码规范。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/92799.html