识别线程安全-共享变量与单实例

刚毕业的时候,总是搞不清什么是线程安全,只记得网上说,只要方法做到可重入,就是线程安全的,晕头晕脑,一头雾水。

今年读Java并发编程,对并发有了进一步的了解,结合我们项目的实际应用,谈一下我对线程安全的认识。

一、共享变量(share varibles)引起线程安全

如果没有共享,就不会有线程安全问题。比如,你写的就是一个简单的helloword程序,不会有线程安全问题。但如果你的程序是一个web项目,并且里面有一个全局适用的缓存对象,那么就会涉及到线程安全问题。

下面是一个静态方法,根据code_id,得到code_name的方法。

public class CodeHelper {
	private static Map<Integer,String> CODE_DATA ;
	public static void initCode(){
		//load from db ..
	}
	public static String getCodeNameById(int codeId){
		if(CODE_DATA==null){
			initCode();
		}
		return CODE_DATA.get(codeId);
	}
}

 变量CODE_DATA就会涉及到线程安全问题。我们考虑,如果同时有两个线程调用getCodeNameById的方法,那么initCode方法就会被执行两边,而这却不是我们希望看到的。所以说,只要涉及到静态变量,我们就要小心了,静态变量,有可能存在线程安全问题。

 

二,单实例引起线程安全

我们知道,spring中的bean默认都是单实例(prototype=singleton)的,也就是说,spring里面的bean,其所有的成员变量都基本上是与静态变量是类似的。bean的任何方法,都必须代是可重入的,而不能在某个方法里面,设置bean的某个值,并且依赖其状态。比如,下面的代码就会出现线程问题。

public class JavaBean {
	private String myname;
	public void aservice(String paraName,int otherPara){
		//在spring的默认配置下在这里设值,另一个方法使用是错误的
		this.myname=paraName;
		bservice();
	}
	private void bservice() {
		String goodName= this.myname;
		//other work
	}
	public String getMyname() {
		return myname;
	}
	public void setMyname(String myname) {
		this.myname = myname;
	}
}

如果有两个线程A和B,同时进入aservice,A线程设置myname="AName",然后在执行到bservice线程阻塞,此时B线程进入,将myname="BName",然后进入bservice得出正确结果而退出。B线程执行后,myname="BName",A线程恢复,在bservice的方法执行时,使用的myname="BName",计算肯定会出错。但如果你每次使用JavaBean的时候,都是new一个,就不会存在线程安全的问题了。

 

 

虽然线程安全是一个不是很容易理解的话题,但上面两个例子却反映了两个最普遍的线程安全问题。遇到线程问题,最快的解决方法就是去掉变量共享。单线程的程序,永远不会出现线程安全问题。

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值