关于synchronized一个字符串的问题

在memcached中我们公司首先根据查询条件获得key,然后查询mem有没有,如果没有将要进行数据库查询,然后add到memecached中,但是如果第一次同一时间大量访问这个key那么同一时间都要访问mysql造成mysql压力巨大,解决方法:

public void method(){

String key = String.valueOf(cityId);

。。。。

synchronized (key) {

。。。

}

}

想不明白key是方法的局部变量,怎么会同步呢,所以写了个测试类

package goodcenter.study;

 

import java.io.IOException;

 

public class TestSyString {

public void test(String str) throws InterruptedException{

String name = str;

synchronized(name){

Thread.sleep(5000);

System.out.println(name);

}

}

 

public static void main(String[] args) throws InterruptedException {

final TestSyString ts = new TestSyString();

Thread thread1 = new Thread(new Runnable() {

 

@Override

public void run() {

try {

ts.test("name");

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

});

Thread thread2 = new Thread(new Runnable() {

 

@Override

public void run() {

try {

ts.test("name");

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

});

thread1.start();

thread2.start();

Thread thread3 = new Thread(new Runnable() {

 

@Override

public void run() {

try {

Thread.sleep(1000);

String str = "name";

synchronized (str) {

System.out.println(str);

}

 

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

});

thread3.start();

Thread.sleep(6000);

String str = "name";

// System.out.println(str);

try {

System.in.read();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

 

}

结果可以看到,居然thread3由于thread1或thread2同步阻塞了,为什么嗯

经过查询才知道,因为JVM有一种优化机制,因为String类型的对象是不可变的,因此当你使用""的形式引用字符串时,如果JVM发现内存已经有一个这样的对象,那么它就使用那个对象而不再生成一个新的String对象,这样是为了减小内存的使用,所以同步阻塞

 

你可能感兴趣的:(synchronized)