有的时候,我们希望使用string作为synchronized的锁,但有的时候字符串a和b虽然内容相同,但是引用不同,
synchronized会当作不同的锁来处理
这个时候我们可以使用String的intern方法,它返回字符串地址的引用,只要字符串内容相同,常量池里面的引用一定相等
如下面的代码,模拟多个线程对字符串分组统计,
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
public class InternTest {
static Map<String ,AtomicInteger> map =new HashMap<>();
static CountDownLatch tcout = new CountDownLatch(1000);
public static void main(String[] args) {
MyThread[] threads=new MyThread[1000];
for(int i=0;i<threads.length;i++) {
if(i%2==0) {
threads[i]=new MyThread("aaa");
}else {
threads[i]=new MyThread("bbb");
}
}
for(int i=0;i<threads.length;i++) {
new Thread(threads[i]).start();
}
try {
tcout.await();//等待所有线程完成
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("map===="+map);
}
static class MyThread implements Runnable{
public String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
synchronized ((name+""+123)) {
AtomicInteger val = map.get(name);
if(val!=null) {
val.incrementAndGet();
map.put(name, val);
}else {
map.put(name, new AtomicInteger(1));
}
tcout.countDown();
}
}
}
}
理想的输出结果是 map===={aaa=500, bbb=500}
但是结果却是多变的,每次都不同
为什么不是aaa和bbb分别等于500呢,说明synchronized的锁有些没有起到作用,导致计数冲突了
因为字符串 name+""+123 不一定引用都相同,要保证synchronized的锁每次生效,必须保证 name+""+123 的锁相同,
所以,只需要改成 name+""+123).intern()就可以可以保证了