java - 具有相同值的字符串文字不会在 Controller 中保留同步锁

标签 java string spring-boot controller synchronized

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

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

第一个线程完成,然后第二个线程启动。我将相同的代码放入 Controller 中,这对于相同的文字不起作用。两个请求进入 block 而不考虑字符串锁。有没有什么办法解决这一问题?这是我测试过的示例,但不起作用。

@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执行两次将创建两个单独的字符串实例,它们不会比较 ==,这意味着对其进行同步不会给出您期望的结果。

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

关于java - 具有相同值的字符串文字不会在 Controller 中保留同步锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58573141/

相关文章:

java - Play Framework : How do I get querystring value inside html template file

java - Spring Cloud Stream Kafka Binder 压缩

javascript - 需要在 javascript 中创建 Json 字符串的帮助

java - 尝试使用字段数组作为参数时出现 NullPointerException

java - 反序列化期间出现 Kryonet 错误

c# - 在 C# 中将字符串拆分为特定格式?

javascript - 如何检查一个字符串是否包含 JavaScript 中预定义数组中存在的子字符串?

不带 Spring Boot 的 Spring Boot 2 执行器

spring - @AutoConfigureWebMvc和@AutoConfigureMockMvc有什么区别?

java - 将时间戳变量添加到应用程序属性中的文件夹路径值