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

String literals with same value doesn't keep a synchronized lock in controller

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

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();
}
}

第一个线程完成,然后第二个线程开始。我在我的控制器中放置了相同的代码,但对于相同的 literals.two 请求进入块而不考虑字符串锁定,这不起作用。有没有什么办法解决这一问题?这是我测试过的示例,但不起作用。

@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");
    }

}

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

if ("abc" == "abc")

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

因此 http://localhost/test/name1 执行两次将创建两个不会比较的单独字符串实例 == 并且这意味着对其进行同步不会给出您期望的结果。

您似乎在尝试同步处理相同的 "test" 值,但允许异步处理不同的测试值。如果是这种情况,那么您可以做一些事情,例如保留正在处理的值的映射,其中 "test" 值是键,并且 Object 的实例存储为用作互斥锁的值。然后在查找互斥体上同步。