• 请不要在回答技术问题时复制粘贴 AI 生成的内容
kikione
V2EX  ›  程序员

String str="abc" 一定会进入到字符串常量池吗?

  •  
  •   kikione · Jul 8, 2021 · 3386 views
    This topic created in 1772 days ago, the information mentioned may be changed or developed.

    String str="abc" 一定会进入到字符串常量池吗?

    如果一定会,为什么我对 str 加锁,锁并没有用。

    17 replies    2021-07-11 11:49:28 +08:00
    Yimkong
        1
    Yimkong  
       Jul 8, 2021 via iPhone
    锁是加给对象的,你这个每次加锁都是都会锁一个新的 String 对象。
    String str=new String("abc"),锁这个就行
    huang119412
        2
    huang119412  
       Jul 8, 2021
    字符串字面量一定进常量池,常量池的字符串不一定不会被回收,synchronized 锁住的对象,当然可以锁住字符串常量对象
    Cy1
        3
    Cy1  
       Jul 8, 2021   ❤️ 1
    你是怎么加锁的?
    public static void main(String[] args) {
    String lock1 = "abc";
    String lock2 = "abc";
    new Thread(() -> {
    synchronized (lock1) {
    System.out.println("t1");
    try {
    TimeUnit.SECONDS.sleep(5);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }, "t1").start();
    new Thread(() -> {
    synchronized (lock2) {
    System.out.println("t2");
    try {
    TimeUnit.SECONDS.sleep(5);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }, "t2").start();
    }
    其中一个线程会被阻塞,明显就是锁的是同一个对象,所以会进 字符串常量池
    lululau
        4
    lululau  
       Jul 8, 2021
    都在背面试题吗😂
    3dwelcome
        5
    3dwelcome  
       Jul 8, 2021   ❤️ 1
    java 判断是不是一个对象,直接相等就可以了,都不用上锁。

    如果进字符串常量池,就会相等。
    aragakiyuii
        6
    aragakiyuii  
       Jul 8, 2021
    OctopusGO
        7
    OctopusGO  
       Jul 9, 2021
    是的,字面量都会进
    kikione
        8
    kikione  
    OP
       Jul 9, 2021
    @Cy1 你好,这是我的测试代码,在 controller 中

    @GetMapping("/concurrency")
    public String testConcurrency(Integer num,String id) throws InterruptedException {
    synchronized (id){
    log.info(Thread.currentThread().getName()+":拿到锁");
    orderAservice.changePrice(num,id);
    }
    log.info(Thread.currentThread().getName()+":释放锁");

    return "success";
    }
    MrGoooo
        9
    MrGoooo  
       Jul 9, 2021
    @kikione 请求的数据过来时是以 byte[]格式过来的,怎么将 byte[]转成 String 呢?肯定是调用了 new String(byte[]),所以就算每次传过来的 id 相同,也无法锁住,因为调用了 new String(),导致对象不同.
    MrGoooo
        10
    MrGoooo  
       Jul 9, 2021
    @kikione 你可以试试将每次请求过来的 id 都放在一个 list 里面,然后用"=="比较,肯定是不同的.
    Cy1
        11
    Cy1  
       Jul 9, 2021
    @kikione #8 楼已经跟你解释明白了
    kikione
        12
    kikione  
    OP
       Jul 9, 2021
    @zj1403762235 谢谢大佬,byte[] 给了我思路,谢谢
    kikione
        13
    kikione  
    OP
       Jul 9, 2021
    @Cy1 谢谢,恍然大悟,我再研究一下
    Aruforce
        14
    Aruforce  
       Jul 9, 2021
    @kikione 锁的又不是 value,是 reference 的地址也就是 id 具体的地址...而这个 id 地址 每次方法执行都不一样;

    这里的 id 不是 C 的 char * str = "predefinedstr" 语句 里面的 str
    这里的 id 是 C 的 char str [] ="predefinedstr" 的 str....
    所以。。。。
    Cy1
        15
    Cy1  
       Jul 9, 2021
    @kikione 既然你用 SpringMVC 了,你倒是可以顺便研究一下 SpringMVC 是怎么生成这个 String id 的,以及怎么调用你这个方法的。大概这个顺序
    org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest
    org.springframework.web.method.support.InvocableHandlerMethod#getMethodArgumentValues
    org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#resolveArgument
    org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver#resolveArgument
    MrGoooo
        16
    MrGoooo  
       Jul 9, 2021
    @kikione 刚开始我也有点不知道咋解释,后来想到数据是以字节流传输的,想到字节流转成字符串的过程应该是用了 new String()
    kikione
        17
    kikione  
    OP
       Jul 11, 2021
    @Cy1 谢谢!
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2594 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 52ms · UTC 16:01 · PVG 00:01 · LAX 09:01 · JFK 12:01
    ♥ Do have faith in what you're doing.