synchronized加锁String踩坑日记

synchronized加锁String踩坑日记

本文参考 https://juejin.im/post/59fffddc5188253d6816f9c1 JVM内存分布

我们知道String.intern()方法会判断该字符串是否存在常量池中,如果存在直接获取,不存在将当前字符串放到常量池中

  1. String 分情况存在于常量池跟JVM堆中,首先让我们来看一下例子一:

    public class TestStringSycn { public static void main(String[] args) { String a = "a"+"b"; System.out.println(a); } }

我们使用javap -c TestStringSycn.class来看编译器如何帮我们解析的:

1$ javap -c TestStringSycn.class 2Compiled from "TestStringSycn.java" 3public class TestStringSycn { 4 public TestStringSycn(); 5 Code: 6 0: aload_0 7 1: invokespecial #1 // Method java/lang/Object."<init>":()V 8 4: return 9 10 public static void main(java.lang.String[]); 11 Code: 12 0: ldc #2 // String ab 13 2: astore_1 14 3: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream; 15 6: aload_1 16 7: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 17 10: return 18} 19 20 21

我们可以看到,编辑器直接是帮我们直接拼接在一起,也就是说这里其实会在常量池里面存在 ab 这个常量 2. 例子二:

1public class TestStringSycn { 2 public static void main(String[] args) { 3 String a = "key"; 4 String b = "zzz"; 5 String c = a+ b; 6 System.out.println(c); 7 } 8} 9$ javap -c TestStringSycn.class 10Compiled from "TestStringSycn.java" 11public TestStringSycn { 12 public TestStringSycn(); 13 Code: 14 0: aload_0 15 1: invokespecial #1 // Method java/lang/Object."<init>":()V 16 4: return 17 18 public static void main(java.lang.String[]); 19 Code: 20 0: ldc #2 // String key 21 2: astore_1 22 3: ldc #3 // String zzz 23 5: astore_2 24 6: new #4 // class java/lang/StringBuilder 25 9: dup 26 10: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V 27 13: aload_1 28 14: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 29 17: aload_2 30 18: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 31 21: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 32 24: astore_3 33 25: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 34 28: aload_3 35 29: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 36 32: return 37} 38 39 40

我们可以看到,这里采用的是StringBuilder直接帮我们拼接而成,最后调用toString()方法,所以每次都会在堆上面生成一个String对象。

回到主题

当我们使用synchronized加锁String的时候,我们需要保证当前加锁的key是唯一的,通过例子1,2知道。如果要加锁String,最好是加锁String.intern()方法。eg:

1public class TestStringSycn { 2 public static void main(String[] args) { 3 String type = "order"; 4 String id = "1"; 5 String key = type + id; 6 synchronized (key.intern()) { 7 //执行方法 8 } 9 } 10}

黑搜丶D

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Opencv中Mat矩阵相乘——点乘、dot、mul运算详解

Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593