具有相同值的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 楼答案
编译器将优化相同值的字符串,并使它们成为代码的一部分时完全相同的实例,如中所示:
但是,如果字符串是在运行时创建的,就像在您的例子中一样,字符串测试是从URL解析的,那么它不会以相同的方式进行优化,它是它自己的实例
因此,执行两次http://localhost/test/name1将创建两个单独的字符串实例,它们不会比较==这意味着在其上进行同步不会得到预期的结果
似乎您正试图使相同“测试”值的处理同步,但允许不同的测试值异步处理。如果是这种情况,那么您可以做一些事情,比如保留正在处理的值的映射,其中“test”值是键,对象的实例存储为用作互斥对象的值。然后在查找互斥对象后在互斥对象上进行同步