Java Synchronized锁失败案例及解决方案
synchronized关键字,一般称之为”同步锁“,用它来修饰需要同步的方法和需要同步代码块,默认是当前对象作为锁的对象。
同步锁锁的是同一个对象,如果对象发生改变,则锁会不生效。
锁失败的代码:
public class IntegerSynTest {
//线程实现Runnable接口
private static class Worker implements Runnable{
private Integer num;
public Worker(Integer num){
this.num=num;
}
@Override
public void run() {
synchronized (num){
Thread thread = Thread.currentThread();
//System.identityHashCode:返回原生的hashCode值,不管Object对象是被重写;空引用的哈希代码为零
System.out.println(thread.getName()+"--@:---"+System.identityHashCode(num));
num++;
System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
}
}
public static void main(String[] args) {
Worker worker = new Worker(1);
for (int i = 0; i < 5; i++) {
new Thread(worker).start();
}
}
}
}
锁失败的运行结果:

锁失败的原因:
1.num++ 的 .class 实现是这样的 Integer integer1 = this.num, integer2 = this.num = Integer.valueOf(this.num.intValue() + 1);
2.查看 Integer.valueOf()的源代码

这时发现,它是重新 new出一个新的Integer,这样的话,每 ++一次,那么就会产生一个新的对象,而Synchronize锁是锁同一个对象,当锁不同对象时,则会锁失败。
解决方法:
Synchronized同步锁只要锁的对象不发生改变即可,那么由此只需要声明一个对象,不修改它,锁这一个对象即可(还有其他方法暂不一一列举,以后也不会列举了)。
锁成功的代码
public class IntegerSynTest {
//线程实现Runnable接口
private static class Worker implements Runnable{
private Integer num;
/**
* ---重点看这里---
* 声明要锁的对象
* ---重点看这里---
*/
private Object object = new Object();
public Worker(Integer num){
this.num=num;
}
@Override
public void run() {
//修改锁对象
synchronized (num){
Thread thread = Thread.currentThread();
//System.identityHashCode:返回原生的hashCode值,不管Object对象是被重写;空引用的哈希代码为零
System.out.println(thread.getName()+"--@:---"+System.identityHashCode(num));
num++;
System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
}
}
public static void main(String[] args) {
Worker worker = new Worker(1);
for (int i = 0; i < 5; i++) {
new Thread(worker).start();
}
}
}
}
锁成功的运行结果:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
相关文章
Java中反射的"暴破"机制(SetAccessible方法)详解
这篇文章主要为大家详细介绍了Java中反射的"暴破"机制,以及如何利用这一机制实现访问非公有属性,方法,和构造器,文中示例代码讲解详细,感兴趣的可以了解一下2022-08-08
SpringBoot集成ShardingSphere实现数据库分表
ShardingSphere 是一个开源的分布式数据库中间件,旨在为应用提供数据库分片、读写分离、分布式事务等功能,下面我们来看看SpringBoot如何集成ShardingSphere实现数据库分表吧2024-12-12
Java8加java10等于Java18的版本查看及特性详解
这篇文章主要为大家介绍了Java 8加java10等于Java18的各个版本要点详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2022-06-06
springboot+jwt+springSecurity微信小程序授权登录问题
这篇文章主要介绍了springboot+jwt+springSecurity微信小程序授权登录问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2021-01-01
在Mac下IDEA安装并使用protobuf方式(Java)
这篇文章主要介绍了在Mac下IDEA安装并使用protobuf方式(Java),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2023-11-11


最新评论