synchoronized 为什么不能锁 int 或者 long 类型

news2024/11/16 19:02:01

前言

synchronized(Object)
不能用String常量
因为字符串常量是在内存中同一个地方。如果两个线程锁一个,可能导致死锁。一个线程多次可能导致重入。

也不能用Integer,Long等基础类型。
因为当锁定int或者long时, jvm就会调用Interger.valueOf()生成一个新的对象,所以锁不会失效
看源码可知,java会把-128到127所对应的包装类都给缓存起来,分别存入了IntegerCache和LongCache
而当锁的值大于127之后,就会新建一个对象,在堆上产生,这时,锁就会失效。


synchoronized 为什么不能锁 int 或者 long 类型

  • 前言
  • 1 测试代码
  • 2 源码分析
  • 3 阿里巴巴开发规范

1 测试代码

@Test
fun lockWithPrimitiveType() {

    val startTime = Instant.now()
    Thread {
        while (true) {
            synchronized(100L) {
                TimeUnit.SECONDS.sleep(2L) // 模拟业务代码耗时
                val endTime = Instant.now()
                val duration = Duration.between(startTime, endTime)
                println("current thread:${Thread.currentThread().name}, I am guild one, seconds: ${duration.seconds}")
            }
        }
    }.start()

    Thread {
        while (true) {
            synchronized(100L) {
                TimeUnit.SECONDS.sleep(2L) // 模拟业务代码耗时
                val endTime = Instant.now()
                val duration = Duration.between(startTime, endTime)
                println("current thread:${Thread.currentThread().name}, I am guild two, seconds: ${duration.seconds}")
            }
        }
    }.start()

    while (true) {}
}


让我们来看一下打印结果:

current thread:Thread-3, I am guild one, seconds: 2
current thread:Thread-4, I am guild two, seconds: 4
current thread:Thread-4, I am guild two, seconds: 6
current thread:Thread-4, I am guild two, seconds: 8
current thread:Thread-4, I am guild two, seconds: 10
current thread:Thread-4, I am guild two, seconds: 12
current thread:Thread-4, I am guild two, seconds: 14
current thread:Thread-4, I am guild two, seconds: 16
current thread:Thread-4, I am guild two, seconds: 18
current thread:Thread-4, I am guild two, seconds: 20

从日志来看,Thread-3线程在执行业务代码的时候,Thread-4线程并没有被执行(阻塞等待)。Thread-4线程在执行业务代码的时候, Thread-3线程也没有被执行。由此可见,锁已经生效了。于是得出了一个结论:“synchornized 锁一个 long 类型的整数是可行的”。
可事实是真是这样吗?
下面对代码做一个简单的修改,将 synchronzied(100L) 改为 synchronized(1000L),再进行测试。

@Test
fun lockWithPrimitiveType() {

    val startTime = Instant.now()
    Thread {
        while (true) {
            synchronized(1000L) { // 将 100L 改为 1000L
                TimeUnit.SECONDS.sleep(2L) // 模拟业务代码耗时
                ..... // 与之前代码一致
            } 
        }
    }.start()

    Thread {
        while (true) {
            synchronized(1000L) { // 将 100L 改为 1000L
                TimeUnit.SECONDS.sleep(2L) // 模拟业务代码耗时
                ...... // 与之前代码一致
            }
        }
    }.start()

    while (true) {}
}


让我们继续看一下打印结果:

current thread:Thread-4, I am guild two, seconds: 2
current thread:Thread-3, I am guild one, seconds: 2
current thread:Thread-4, I am guild two, seconds: 4
current thread:Thread-3, I am guild one, seconds: 4
current thread:Thread-4, I am guild two, seconds: 6
current thread:Thread-3, I am guild one, seconds: 6
current thread:Thread-3, I am guild one, seconds: 8
current thread:Thread-4, I am guild two, seconds: 8
current thread:Thread-4, I am guild two, seconds: 10
current thread:Thread-3, I am guild one, seconds: 10


这个时候,我们会发现,Thread-4线程在执行业务代码的时候,Thread-3线程同时也在执行业务代码,那么这个时候,锁为什么没有生效呢?
答案是:synchronized 只能锁对象,那么当我们传入 int 类型或者 long 类型整数的时候,java 会调用 Integer.valueOf() 或者 Long.valueOf() 方法将它们转为一个新的对象,所以锁不会生效。
那么为什么锁 100L 这个整数时,锁会生效,这个时候我们看源码可以得知,Java 会把 -128 到 127 所对应的包装类对象都给缓存起来,分别存入了 IntegerCache 和 LongCache 对象里。

2 源码分析

Integer.valueOf() 方法

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high) // 如果 i >= -128 且 i <= 127
        return IntegerCache.cache[i + (-IntegerCache.low)]; // 返回 IntegerCache 里的对象
    return new Integer(i); // 返回一个新对象
}


IntegerCache 类

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        int h = 127
        ...... // 省略非关键性代码
        heigh = h

        cache = new Integer[(high - low) + 1]; // 设置数组的大小(256)
        int j = low;
        for(int k = 0; k < cache.length; k++) // 为 -128 到 127 之间的整数创建 Integer 对象
            cache[k] = new Integer(j++); 
       ...... // 省略非关键性代码
    }

    private IntegerCache() {}
}

Long.valueOf() 方法

public static Long valueOf(long l) {
    final int offset = 128;
    if (l >= -128 && l <= 127) { // will cache
        return LongCache.cache[(int)l + offset]; // 返回 LongCache 里的对象
    }
    return new Long(l); // 返回新对象
}


LongCache 类

private static class LongCache {
    private LongCache(){}

    static final Long cache[] = new Long[-(-128) + 127 + 1];

    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Long(i - 128);
    }
}

可以发现,Integer.valueOf() 与 Long.valueOf 实现方法略有不同,IntegerCache 和 LongCache 实现方法也略有不同,可是结果都是一样的:都是对-128 到 127 之间的整数所对应的包装类对象进行缓存。
为什么实现没有保持统一,我们也不得而知了,我猜可能是实现代码的作者不同吧,哈哈哈。

3 阿里巴巴开发规范

在阿里巴巴开发规范,OOP 规约里第 7 条也有提到这么一项的强制规则。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1435874.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VXLAN网关技术及应用实例详解

1.特性概述 VXLAN是VLAN扩展方案草案&#xff0c;是NVo3中的一种网络虚拟化技术。采用MAC in UDP封装方式&#xff0c;将二层报文用三层协议进行封装&#xff0c;可对二层网络在三层范围进行扩展&#xff0c;同时支持24bits的VNIID ( 16M租户能力&#xff09;&#xff0c;满足…

甲辰龙年,中国科技十大趋势

先给各位拜个早年。 年关岁末&#xff0c;各大科技厂商、研究机构纷纷发布自己研判的新年十大科技趋势。这些内容当然大有裨益&#xff0c;相信热爱科技的读者朋友也没少关注。 但说句掏心窝子的话&#xff0c;种种十大趋势看多了&#xff0c;不免发现两个问题&#xff0c;一个…

vite+vue3发布自己的npm组件+工具函数

记录一下个人最近一次发布npm组件的过程&#xff1a; 一、创建组件和工具函数 执行命令创建一个空项目&#xff1a; npm create vite 创建过程稍微有些慢&#xff0c;不知何故&#xff1f;其中选择vue , 个人暂时使用的JS 。在 src 目录下面创建一个文件 package 存放组件和公…

Antd+React+react-resizable实现表格拖拽功能

1、先看效果 2、环境准备 "dependencies": {"antd": "^5.4.0","react-resizable": "^3.0.4",},"devDependencies": {"types/react": "^18.0.33","types/react-resizable": "^…

【知识图谱+大模型的紧耦合新范式】Think-on-Graph:解决大模型在医疗、法律、金融等垂直领域的幻觉

Think-on-Graph&#xff1a;解决大模型在医疗、法律、金融等垂直领域的幻觉 Think-on-Graph 原理ToG 算法步骤&#xff1a;想想再查&#xff0c;查查再想实验结果 论文&#xff1a;https://arxiv.org/abs/2307.07697 代码&#xff1a;https://github.com/IDEA-FinAI/ToG Think…

【Linux系统学习】1.初识Linux

初识Linux 操作系统概述 初识Linux 虚拟机介绍 VMware WorkStation安装 1.操作系统概述 了解操作系统的作用 了解常见的操作系统 1.1 硬件和软件 计算机由哪两个主要部分组成&#xff1f; 硬件&#xff1a;计算机系统中由电子&#xff0c;机械和光电元件等组成的各种物理装置的…

AI专题:海外科技巨头指引,AI主线逻辑依旧坚挺

今天分享的是AI 系列深度研究报告&#xff1a;《AI专题&#xff1a;海外科技巨头指引&#xff0c;AI主线逻辑依旧坚挺》。 &#xff08;报告出品方&#xff1a;华西证券&#xff09; 报告共计&#xff1a;54页 本周热点:海外科技巨头指引&#xff0c;AI主线逻辑依旧坚挺 硬件…

2、ChatGPT 在数据科学中的应用

ChatGPT 在数据科学中的应用 ChatGPT 可以成为数据科学家的绝佳工具。以下是我所了解到的关于它擅长的地方和不那么擅长的地方。 我从使用 ChatGPT 中学到了一个教训。它在数据科学中非常有帮助,但你必须仔细检查它输出的所有内容。它非常适合某些任务,并且可以非常快速准确…

CSDN2024年我的创作纪念日1024天|不忘初心|努力上进|积极向前

CSDN2024年我的创作纪念日1024天| 学习成长机遇&#xff1a;学习成长收获&#xff1a;2023年度总结数据&#xff1a;2024新领域的探索&#xff1a;日常和自己的感慨&#xff1a;2024憧憬和规划&#xff1a;创作纪念日总结&#xff1a; 学习成长机遇&#xff1a; 大家好&#x…

Aigtek高精度电压源什么作用

高精度电压源是一种能够提供稳定、可靠且精确的电压输出的电子设备。它在科学研究、工程应用和制造业中起着至关重要的作用。以下将详细介绍高精度电压源的作用及其在不同领域的应用。 一、工作原理 稳定性&#xff1a;高精度电压源通常采用精密的电路设计和稳压技术&#xff0…

如何在Termux中使用Hexo结合内网穿透工具实现远程访问本地博客站点

文章目录 前言 1.安装 Hexo2.安装cpolar3.远程访问4.固定公网地址 前言 Hexo 是一个用 Nodejs 编写的快速、简洁且高效的博客框架。Hexo 使用 Markdown 解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。 下面介绍在Termux中安装个人hexo博客并结合…

【openwrt】MT7981 5G WiFi MAC地址不生效问题分析及解决方案

问题描述 MT7981 默认sdk 5G MAC地址根据2.4G MAC地址随机生成,我们写到Factory区域的值不生效 问题分析 查看EEPROM MAC位置 查看MTK EEPROM文档MT7981_EEPROM_Content_Introduction_V10_20211207.pdf可以看到EEPROM里面有两个位置可以存放MAC,0x04~0x09 和0x0a~0x0f 查看…

【芯片设计- RTL 数字逻辑设计入门 6 -- 带同步复位的D触发器 RTL实现及testbench 验证】

文章目录 带同步复位的D触发器Verilog 代码testbench 代码编译及仿真问题小结 带同步复位的D触发器 同步复位 &#xff1a;复位只能发生在在clk信号的上升沿&#xff0c;若clk信号出现问题&#xff0c;则无法进行复位。 Verilog 代码 // timescale ins/1nsmodule flopr (inpu…

博途PLC报警字FC(字寄存器按位访问)

博途PLC的字寄存器按位访问和拆分,请查看下面文章链接: https://rxxw-control.blog.csdn.net/article/details/121727057https://rxxw-control.blog.csdn.net/article/details/121727057西门子触摸屏报警都是以字为地址访问,所以离散报警信号我们需要将其组合为报警字输出,…

docker重建镜像

DockerFile如下&#xff1a; FROM k8s-registry.qhtx.local/base/centos7-jdk8-haitong0704RUN yum -y update && yum install -y python3-devel && yum install -y python36 RUN mv /usr/bin/python /usr/bin/python_old RUN ln -s /usr/bin/python3 /usr/bi…

LeetCode:9.回文数,对整数的反转操作

博主本想找个简单的题水一下&#xff0c;结果太久没写这块的代码&#xff0c;直接写着宕机着&#xff0c;十分难受&#xff0c;最后还调试了几下&#xff0c;悲&#xff0c; 目录 题目&#xff1a; 思路&#xff1a; 官方代码&#xff08;反转一半的&#xff09;&#xff1a…

人工智能专题:量子汇编语言和量子中间表示发展白皮书

今天分享的是人工智能系列深度研究报告&#xff1a;《人工智能专题&#xff1a;量子汇编语言和量子中间表示发展白皮书》。 &#xff08;报告出品方&#xff1a;量子信息网络产业联盟&#xff09; 报告共计&#xff1a;78页 量子计算与量子编程概述 随着社会生产力的发展&am…

2024 年十大 Vue.js UI 库

Vue.js 是一个流行的 JavaScript 框架&#xff0c;它在前端开发者中越来越受欢迎&#xff0c;以其简单、灵活和易用性而闻名。 Vue.js 如此受欢迎的原因之一是它拥有庞大的 UI 库生态系统。 这些库为开发人员提供了预构建的组件和工具&#xff0c;帮助他们快速高效地构建漂亮…

Go语言每日一练链表篇(一)

题目传送门 牛客面试必刷101题 ----------反转链表 题目以及答案源码 反转链表 题目 解题方法 递归函数遍历链表并反转 package main import _"fmt" import . "nc_tools" /** type ListNode struct{* Val int* Next *ListNode* }*//*** 代码中的…

【数据分享】1929-2023年全球站点的逐月平均能见度(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、能见度等指标&#xff0c;说到气象数据&#xff0c;最详细的气象数据是具体到气象监测站点的数据&#xff01; 之前我们分享过1929-2023年全球气象站点的逐月平均气温数据、逐月最高气温数据…