有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

具有相同值的java字符串文本不会在控制器中保持同步锁定

我知道字符串文字指向同一个对象,并且对相同的值具有相同的引用。因此,它正好适合我的同步情况。我测试了下面的代码,它正是我想要的。我希望在相同的字符串上有一个锁,而在字符串不同时没有锁

public class SampleThread extends Thread {
String lock;
public SampleThread(String s) {
    this.lock = s;
}
@Override
public void run() {

    long id = this.getId();
    synchronized (lock) {
        for (int i = 0; i < 1000; i++) {
            System.out.println("thread with id: "+id);
        }
    }
}

public static void main(String[] args) {

    SampleThread s1 = new SampleThread("mina");
    SampleThread s2 = new SampleThread("mina");

    s1.start();
    s2.start();
}
}

第一个线程完成,然后第二个线程开始。我把相同的代码放在我的控制器中,这对相同的文本不起作用。两个请求进入块而不考虑字符串锁。有办法解决这个问题吗?这是我测试过的样本,不起作用

@RequestMapping("/test/{name}")
public void test(@PathVariable("name") String test) throws InterruptedException {

    String a = test;
    synchronized (String.valueOf(a)) {
        System.out.println("first");
        TimeUnit.SECONDS.sleep(4);
        System.out.println("finish");
    }

}

共 (1) 个答案

  1. # 1 楼答案

    编译器将优化相同值的字符串,并使它们成为代码的一部分时完全相同的实例,如中所示:

    if ("abc" == "abc")
    

    但是,如果字符串是在运行时创建的,就像在您的例子中一样,字符串测试是从URL解析的,那么它不会以相同的方式进行优化,它是它自己的实例

    因此,执行两次http://localhost/test/name1将创建两个单独的字符串实例,它们不会比较==这意味着在其上进行同步不会得到预期的结果

    似乎您正试图使相同“测试”值的处理同步,但允许不同的测试值异步处理。如果是这种情况,那么您可以做一些事情,比如保留正在处理的值的映射,其中“test”值是键,对象的实例存储为用作互斥对象的值。然后在查找互斥对象后在互斥对象上进行同步