当前位置: 首页 > article >正文

使用synchronized锁住字符串

我们使用synchronized 可以锁住字符串:

public static void testSynchronized1(String str) {
    synchronized (str) {
        try {
            Thread.sleep(3000);
            System.out.println("接收到了:" + str);
        } catch (Exception ignore) {}
    }
}


public static void main(String[] args) {
    new Thread(() -> testSynchronized1("字符串1")).start();
    new Thread(() -> testSynchronized1("字符串2")).start();
    new Thread(() -> testSynchronized1("字符串3")).start();
    new Thread(() -> testSynchronized1("字符串2")).start();
    new Thread(() -> testSynchronized1("字符串2")).start();
}

但这样有一个问题:直接写的字符串是在常量池里面的,若是new出来的,即使字面量一致,也不是同一对象:

public static void main(String[] args) {
    new Thread(() -> testSynchronized1(new String("字符串1"))).start();
    new Thread(() -> testSynchronized1(new String("字符串2"))).start();
    new Thread(() -> testSynchronized1(new String("字符串3"))).start();
    new Thread(() -> testSynchronized1(new String("字符串2"))).start();
    new Thread(() -> testSynchronized1(new String("字符串2"))).start();
}

解决该问题的方法为:使用字符串的intern方法,获取(不存在则添加)常量池中的引用

public static void testSynchronized1(String str) {
    synchronized (str.intern()) {
        try {
            Thread.sleep(3000);
            System.out.println("接收到了:" + str);
        } catch (Exception ignore) {}
    }
}


public static void main(String[] args) {
    new Thread(() -> testSynchronized1(new String("字符串1"))).start();
    new Thread(() -> testSynchronized1(new String("字符串2"))).start();
    new Thread(() -> testSynchronized1(new String("字符串3"))).start();
    new Thread(() -> testSynchronized1(new String("字符串2"))).start();
    new Thread(() -> testSynchronized1(new String("字符串2"))).start();
}

但又带来新的问题,可以看到,另一个方法也锁了该字符串的话,那它们竞争的是同一个锁,达不到锁粒度仅为该方法的目的:

public static void testSynchronized1(String str) {
    synchronized (str.intern()) {
        try {
            Thread.sleep(3000);
            System.out.println("接收到了:" + str);
        } catch (Exception ignore) {}
    }
}

public static void testSynchronized2(String str) {
    synchronized (str.intern()) {
        try {
            Thread.sleep(5000);
            System.out.println("方法2接收到了:" + str);
        } catch (Exception ignore) {}
    }
}


public static void main(String[] args) {
    new Thread(() -> testSynchronized1(new String("字符串1"))).start();
    new Thread(() -> testSynchronized2(new String("字符串2"))).start();
    new Thread(() -> testSynchronized1(new String("字符串3"))).start();
    new Thread(() -> testSynchronized1(new String("字符串2"))).start();
    new Thread(() -> testSynchronized1(new String("字符串2"))).start();
}

我这边想到的一个解决思路为:给每个方法加一个唯一的字符串标识,再和参数组装为新的字符串:

public static void testSynchronized1(String str) {
    String intern = new String(str + "testSynchronized1").intern();
    synchronized (intern) {
        try {
            Thread.sleep(3000);
            System.out.println("接收到了:" + str);
        } catch (Exception ignore) {}
    }
}

public static void testSynchronized2(String str) {
    String intern = new String(str + "testSynchronized2").intern();
    synchronized (intern) {
        try {
            Thread.sleep(5000);
            System.out.println("方法2接收到了:" + str);
        } catch (Exception ignore) {}
    }
}


public static void main(String[] args) {
    new Thread(() -> testSynchronized1(new String("字符串1"))).start();
    new Thread(() -> testSynchronized2(new String("字符串2"))).start();
    new Thread(() -> testSynchronized1(new String("字符串3"))).start();
    new Thread(() -> testSynchronized1(new String("字符串2"))).start();
    new Thread(() -> testSynchronized1(new String("字符串2"))).start();
}

http://www.kler.cn/news/317497.html

相关文章:

  • Shire 智能体市场:IDE 一键安装多智能体,协同打造集体智慧 Copilot
  • 迎国庆-为祖国庆生python、Java、C各显神通
  • 【Python】数据可视化之分布图
  • 联影医疗嵌入式面试题及参考答案(3万字长文)
  • wpf,工具栏上,最小化按钮的实现
  • ubuntu 系统下,安装stable diffusion解决下载速度慢的问题
  • (十五)、把自己的镜像推送到 DockerHub
  • 数模方法论-无约束问题求解
  • 科龙睡眠空调小耳朵LF上线,“亲身”答疑空调一天多少度电
  • 【二十五】【QT开发应用】无边窗窗口鼠标拖动窗口移动,重写mousePressEvent,mouseMoveEvent函数
  • 专属文生图助手——SD3+ComfyUI文生图部署步骤
  • 安卓Settings值原理源码剖析存储最大的字符数量是多少?
  • css设置动态数组渲染及中间线平均分开显示
  • IMX6UL开发板中断实验(三)
  • 深度学习02-pytorch-01-张量的创建
  • 使用python-pptx拆分PPT文档:将一个PPT文件拆分成多个小的PPT文件
  • 某yandex图标点选验证码逆向
  • 使用双向 LSTM 和 CRF 进行中文命名实体识别
  • Spring全家桶
  • 图为科技大模型一体机,智领未来社区服务
  • C++中stack类和queue类
  • vue3/Element-Plus/路由的使用
  • Flask-Migrate的使用
  • 学生宿舍管理:Spring Boot技术实现
  • 国内外动态sk5
  • react hooks--useRef
  • 结构设计模式 -装饰器设计模式 - JAVA
  • dockerfile案例
  • unity将多层嵌套的结构体与json字符串相互转化
  • 定制智慧科技展厅方案:哪些细节是成功的秘诀?