Java Synchronized锁失败案例及解决方案
作者:踏步 发布时间:2023-10-25 12:33:47
标签: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();
}
}
}
}
锁成功的运行结果:
来源:https://www.cnblogs.com/mjtabu/p/12702721.html


猜你喜欢
- SpringBoot配置外部静态资源映射使用场景实际项目中,特别是前后端分离的项目,SpringBoot后台打包(jar包)后,以jar包形
- 1、LongAdder由来LongAdder类是JDK1.8新增的一个原子性操作类。AtomicLong通过CAS算法提供了非阻塞的原子性操
- spring boot 秉承约定优于配置,spring boot在静态资源的处理上就已经默认做了处理。1.默认资源映射映射”/**”的路径到
- 随着互联网的飞跃式发展,移动支付已越来越受欢迎并且已成为常态,很多三方支付公司推出了很多支付方式如快捷支付、认证支付、扫码支付等等。快捷支付
- 1.构建springboot项目2.打包应用3.编写dockerfile4.构建镜像5.发布运行![root@localhost demo]
- 修改好的代码下载地址:https://github.com/Vico-H/Launcher•不显示开机向导-----------------
- C# 中闭包(Closure)详解这个问题是在最近一次英格兰 Brighton ALT.NET Beers 活动中提出来的。我发现,如果不用
- 前言如今发短信功能已经成为互联网公司的标配,本篇文章将一步步实现java发送短信考察了许多提供短信服务的三方,几乎所有都需要企业认证才可以使
- 一、JDBC简介JDBC是连接java应用程序和数据库之间的桥梁。什么是JDBC?Java语言访问数据库的一种规范,是一套API。JDBC
- 目录一、单例模式饿汉模式懒汉模式懒汉模式二、堵塞队列实现BlockingQueue三、定时器总结一、单例模式单例模式是一种设计模式,针对一些
- Spring Boot简介SpringBoot为了简化在开发基于 Spring的项目的难度,减少了哪些繁杂的配置,从而让开发基于 Sprin
- 1、前言随着技术的发展,微信的一系列服务渗透进了我们的生活,但是我们应该怎样进行微信方面的开发呢。相信很多的小伙伴们都很渴望知道吧。这篇文章
- 目录单一职责原则接口隔离原则开闭原则里氏替换原则依赖倒置原则迪米特法则笔者作为一个菜鸟,会尝试以简单的代码和容易理解的语句去解释这几种原则的
- 目录生成器设计类图: 实现代码:优点:用途与缺点:责任链设计类图:实现代码:优点:用途和缺点:总结生成器生成器模式:封装一个产品的
- 水仙花数:水仙花数是三位数,它的各位数字的立方和等于这个三位数本身,例如:370=33+73+00;371=33+73+13,370、371
- 1.下载jdk8 1)官网下载地址Java8下载官网地址:http://www.oracle.com/technetwork/java/ja
- 1 读取操作系统和CLR的版本OperatingSystem os = System.Environment.OSVersion; Cons
- 前言Android studio依赖项目是使用gradle管理的,依赖一个项目、一个jar包、一个工程,都可以在这里进行配置,本文将给大家详
- Windows系统启动Java程序会弹出黑窗口。黑窗口有几点不好。首先它不美观;其次容易误点导致程序关闭;但最让我匪夷所思的是:将鼠标光标选
- 首先是main.xml文件代码如下:<LinearLayout xmlns:android="http://schemas.