String对象作为同步锁遇到的有关问题
String对象作为同步锁遇到的问题
这个程序有100个线程,每个线程都对一个值进行加二操作,但"加二"这个行为是同步的,互不干涉(即其他线程会出现阻塞,等待释放锁),所以控制台只会输出偶数.如果出现干涉,就会输出奇数信息.
这个同步方式是使用同步代码块,对字符串对象进行加锁.
但问题出现了:
跟
作为同步锁有什么不同?为什么前者不会产生干涉?后者会有干涉,出现奇数很好理解,因为每个线程锁定的都是不同的String对象
以下是详细代码:
至于我为什么不用同步方法或锁其他对象,可以看这里:http://www.cnblogs.com/mushroom/p/4199701.html
------解决思路----------------------
String是final类,每次使用+或者new之后都会在内存中创建新的String对象,而如果String=常量时,String常量存在常量池中,不会重新创建,所以在你的栗子中,那个String其实每次都不一样,导致加锁失败。fyi。
这个程序有100个线程,每个线程都对一个值进行加二操作,但"加二"这个行为是同步的,互不干涉(即其他线程会出现阻塞,等待释放锁),所以控制台只会输出偶数.如果出现干涉,就会输出奇数信息.
这个同步方式是使用同步代码块,对字符串对象进行加锁.
synchronized(key){/*some code*/}
但问题出现了:
String key = "key_for_add";
跟
String key = new String("key_for_add");
作为同步锁有什么不同?为什么前者不会产生干涉?后者会有干涉,出现奇数很好理解,因为每个线程锁定的都是不同的String对象
以下是详细代码:
public class ExecutorsDemo2{
private int currentEvenValue = 0;
private String defaultKey;
public ExecutorsDemo2(String key){
this.defaultKey = key;
}
public static void main(String[] args){
ExecutorsDemo2 ed = new ExecutorsDemo2("key1");
ExecutorService exec = Executors.newCachedThreadPool();
for(int i=0;i<100;i++){
exec.execute(new AddTask(ed));
}
exec.shutdown();
}
public void add(String skey){
String key = skey; //同步
//String key = "key_for_add"; //同步,为什么?
//String key = new String("key_for_add"); //不同步,出现奇数
//String key = skey + "_for_add"; //不同步,出现奇数
//String key = new StringBuilder(skey).toString(); //不同步,出现奇数
//String key = new StringBuilder(skey).append("_for_add").toString(); //不同步,出现奇数
synchronized(key){
this.currentEvenValue++;
Thread.yield();
this.currentEvenValue++;
int result = currentEvenValue;
if(result%2!=0){
System.out.println("*** error : value is "+result);
}else{
System.out.println("value is "+currentEvenValue);
}
}
}
public String getActionKey(){
return this.actionKey;
}
}
public class AddTask implements Runnable{
public ExecutorsDemo2 ed;
public AddTask(ExecutorsDemo2 ed){
this.ed = ed;
}
public void run() {
ed.add(ed.getActionKey());
}
}
至于我为什么不用同步方法或锁其他对象,可以看这里:http://www.cnblogs.com/mushroom/p/4199701.html
------解决思路----------------------
String是final类,每次使用+或者new之后都会在内存中创建新的String对象,而如果String=常量时,String常量存在常量池中,不会重新创建,所以在你的栗子中,那个String其实每次都不一样,导致加锁失败。fyi。