`
xfei6868
  • 浏览: 68612 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

维护有感3 -- 被滥用的synchronized

阅读更多
同样要先看一段代码,这是一段方法内部的代码:
StringBuffer temp = new StringBuffer(64);
    synchronized (temp) {
	String cgbh = Decoder.getParameter(request, "cgbh");
			
	temp.append("INSERT INTO LWZZWCRXX (ID, XMBH, ZGH, XM) (SELECT ");
	temp.append(" IDC_U_KYMIS.KY_XMRYXX_SEQ.NEXTVAL, CGBH, '");
	temp.append(UserToken.getUserid(request)).append("','");			
	temp.append(UserToken.getUser(request).getUserName() + "'");
	temp.append(" FROM ( ");
	temp.append("SELECT NVL(TO_CHAR(MAX(TO_NUMBER(CGBH))), '").append(cgbh).append("' || '0000') CGBH");
	temp.append(" FROM LWZZ WHERE CGBH LIKE '").append(cgbh).append("%'))");
			
	return temp.toString();
    }


先不说代码中变量的命名是否显得苍白,主要的问题就是这个synchronized 使用,
temp 是一个局部变量,一个方法内的局部变量,而java的方法的执行每次调用都会产生不懂的方法内局部变量,那真不知道 synchronized (temp)的用处在什么地方。

补充:

    java中方法是线程安全的,对于局部变量来说,根本没有必要用synchronized,如果需要用到synchronized来做特殊处理,那肯定是自己的设计出了问题,要选择修改自己的策略,而不是通过这样的办法。甚至本人觉得局部变量的就是用StringBuilder也不需要做同步,用同步肯定自己策略本身就是危险的。
3
0
分享到:
评论
3 楼 xfei6868 2009-12-09  
exchange 写道
...
temp在这里是作为一个对象锁来用的,你也可以另外随便new一个什么对象来当同步锁,效果差不多,同步是对temp一系列的append操作进行同步.你可以试着去掉这个同步,用多线程来调用这个方法,看看结果,质疑之前最好给点实验数据,一句话,用数据来支持你的观点.


感觉上次给出的j2ee容器对java的方法的调用是安全的论据没办法支持自己的想法,所以必须做个试验让自己对多线程也更了解些。

于是写了个例子:

public class ThreadClass implements Runnable {

	@Override
	public void run() {
		
		for (int i = 0; i < 10; i++)
		{
			StringBuffer strBuf = new StringBuffer();
			strBuf.append("run" + i + ": ");
			strBuf.append("0");
			strBuf.append("1");
			strBuf.append("2");
			strBuf.append("3");
			strBuf.append("4");
			strBuf.append("5");
			strBuf.append("6");
			strBuf.append("7");
			strBuf.append("8");
			strBuf.append("9");
			System.out.println(strBuf.toString());
			
			Test t = new Test();
			t.testStr(i);
		}		
	}

}

class Test {
	public void testStr(int i) {
		StringBuffer strBuf = new StringBuffer();
		strBuf.append("test" + i + ": ");
		strBuf.append("0");
		strBuf.append("1");
		strBuf.append("2");
		strBuf.append("3");
		strBuf.append("4");
		strBuf.append("5");
		strBuf.append("6");
		strBuf.append("7");
		strBuf.append("8");
		strBuf.append("9");
		
		System.out.println(strBuf.toString());
	}
}


测试类:


public class TheadTest {

	public static void main(String[] args) {
		ThreadClass threadObj = new ThreadClass();
		new Thread(threadObj).start();
		new Thread(threadObj).start();
		new Thread(threadObj).start();
		new Thread(threadObj).start();
		new Thread(threadObj).start();
		new Thread(threadObj).start();
		new Thread(threadObj).start();
		new Thread(threadObj).start();
		new Thread(threadObj).start();
		new Thread(threadObj).start();
		new Thread(threadObj).start();
		new Thread(threadObj).start();
	}

}



从测试结果上看,可以看出局部变量的确不用是不用synchronized,因为得到的结果的确是正确的0123456789,同时如exchange 说的同步是对temp一系列的append操作进行同步 ,的确从结果上看,先执行的并不一定是先出结果的,但是觉得还是没必要这样做的,就像很多方法没有使用同步一样,仍然认为这样做没有必要。
同时谢谢exchange的提醒。

测试结果:
run0: 0123456789
run0: 0123456789
run0: 0123456789
run0: 0123456789
run0: 0123456789
run0: 0123456789
run0: 0123456789
run0: 0123456789
run0: 0123456789
run0: 0123456789
run0: 0123456789
run0: 0123456789
test0: 0123456789
run1: 0123456789
test1: 0123456789
run2: 0123456789
test2: 0123456789
test0: 0123456789
run1: 0123456789
test1: 0123456789
run2: 0123456789
test2: 0123456789
run3: 0123456789
test0: 0123456789
run1: 0123456789
test1: 0123456789
run2: 0123456789
test2: 0123456789
run3: 0123456789
test3: 0123456789
run4: 0123456789
test4: 0123456789
run5: 0123456789
test5: 0123456789
run6: 0123456789
test6: 0123456789
run7: 0123456789
test0: 0123456789
run1: 0123456789
test1: 0123456789
run2: 0123456789
test2: 0123456789
run3: 0123456789
test3: 0123456789
run4: 0123456789
test4: 0123456789
run5: 0123456789
test5: 0123456789
run6: 0123456789
test6: 0123456789
run7: 0123456789
test7: 0123456789
run8: 0123456789
test8: 0123456789
run9: 0123456789
test9: 0123456789
test0: 0123456789
test0: 0123456789
run1: 0123456789
test1: 0123456789
run2: 0123456789
test2: 0123456789
test0: 0123456789
run1: 0123456789
test1: 0123456789
run2: 0123456789
test2: 0123456789
run3: 0123456789
test3: 0123456789
run4: 0123456789
test4: 0123456789
run5: 0123456789
test5: 0123456789
run6: 0123456789
test6: 0123456789
run7: 0123456789
test7: 0123456789
run8: 0123456789
test8: 0123456789
run9: 0123456789
test9: 0123456789
run3: 0123456789
test3: 0123456789
run4: 0123456789
test4: 0123456789
run5: 0123456789
test5: 0123456789
run6: 0123456789
test6: 0123456789
run7: 0123456789
test7: 0123456789
run8: 0123456789
test8: 0123456789
run9: 0123456789
test9: 0123456789
test7: 0123456789
run8: 0123456789
run1: 0123456789
test1: 0123456789
run2: 0123456789
test2: 0123456789
run3: 0123456789
test3: 0123456789
run4: 0123456789
test4: 0123456789
run5: 0123456789
test5: 0123456789
run6: 0123456789
test6: 0123456789
run7: 0123456789
test7: 0123456789
run8: 0123456789
test8: 0123456789
run9: 0123456789
test9: 0123456789
test3: 0123456789
run4: 0123456789
test4: 0123456789
run5: 0123456789
test5: 0123456789
run6: 0123456789
test6: 0123456789
run7: 0123456789
test7: 0123456789
run8: 0123456789
test8: 0123456789
run9: 0123456789
test9: 0123456789
test0: 0123456789
run1: 0123456789
test1: 0123456789
run2: 0123456789
test2: 0123456789
run3: 0123456789
test3: 0123456789
run4: 0123456789
test4: 0123456789
run5: 0123456789
test5: 0123456789
run6: 0123456789
test6: 0123456789
run7: 0123456789
test7: 0123456789
run8: 0123456789
test8: 0123456789
run9: 0123456789
test9: 0123456789
test0: 0123456789
run1: 0123456789
test1: 0123456789
run2: 0123456789
test2: 0123456789
run3: 0123456789
test3: 0123456789
run4: 0123456789
test4: 0123456789
run5: 0123456789
test5: 0123456789
run6: 0123456789
test6: 0123456789
run7: 0123456789
test7: 0123456789
run8: 0123456789
test8: 0123456789
run9: 0123456789
test9: 0123456789
test0: 0123456789
test0: 0123456789
run1: 0123456789
test1: 0123456789
run2: 0123456789
test2: 0123456789
run3: 0123456789
test3: 0123456789
run4: 0123456789
test4: 0123456789
run5: 0123456789
test5: 0123456789
run6: 0123456789
test6: 0123456789
run7: 0123456789
test7: 0123456789
run8: 0123456789
test8: 0123456789
run9: 0123456789
test9: 0123456789
run3: 0123456789
test3: 0123456789
run4: 0123456789
test4: 0123456789
run5: 0123456789
test5: 0123456789
run6: 0123456789
test6: 0123456789
run7: 0123456789
test7: 0123456789
run8: 0123456789
test8: 0123456789
run9: 0123456789
test9: 0123456789
test0: 0123456789
run1: 0123456789
run1: 0123456789
test8: 0123456789
run9: 0123456789
test9: 0123456789
test1: 0123456789
run2: 0123456789
test2: 0123456789
run3: 0123456789
test3: 0123456789
run4: 0123456789
test4: 0123456789
run5: 0123456789
test5: 0123456789
run6: 0123456789
test6: 0123456789
run7: 0123456789
test7: 0123456789
run8: 0123456789
test8: 0123456789
run9: 0123456789
test9: 0123456789
test1: 0123456789
run2: 0123456789
test2: 0123456789
run3: 0123456789
test3: 0123456789
run4: 0123456789
test4: 0123456789
run5: 0123456789
test5: 0123456789
run6: 0123456789
test6: 0123456789
run7: 0123456789
test7: 0123456789
run8: 0123456789
test8: 0123456789
run9: 0123456789
test9: 0123456789



2 楼 xfei6868 2009-12-08  
exchange 写道
...
temp在这里是作为一个对象锁来用的,你也可以另外随便new一个什么对象来当同步锁,效果差不多,同步是对temp一系列的append操作进行同步.你可以试着去掉这个同步,用多线程来调用这个方法,看看结果,质疑之前最好给点实验数据,一句话,用数据来支持你的观点.


当然你说的是正确的,可能是我没有说明好这个方法所在的范围内的,j2ee容器对java的方法的调用是安全的,就不存在这个问题了,因为temp是局部变量。
1 楼 exchange 2009-12-07  
...
temp在这里是作为一个对象锁来用的,你也可以另外随便new一个什么对象来当同步锁,效果差不多,同步是对temp一系列的append操作进行同步.你可以试着去掉这个同步,用多线程来调用这个方法,看看结果,质疑之前最好给点实验数据,一句话,用数据来支持你的观点.

相关推荐

Global site tag (gtag.js) - Google Analytics