摘自:http://lianjiajun05.blog.163.com/blog/static/2638954820106310236547/
在spring中默认的service是singleton的,这就造成了一个问题:在有共享变量(比如static变量,有时候我们不得不这么做)的时候,需要考虑到该共享变量的多线程安全问题。
解决这个问题有几个方法:
1.借助支持多线程安全的对象创建方式。如果是static Map类型的变量,在不需要考虑并发的情况下我们可以这么创建
private static Map <T1,T2> MY_MAP = new HashMap <T1,T2>();
但是HashMap是非线程安全的,大家可能会想到HashTable,HashTable使用synchonized方法实现,会造成很大的性能问题。在JDK1.5及以后的版本中新增了一个包 java.util.concurrent,这个包中的方法既能控制并发又不影响性能,这个时候应该这样创建该Map对象:
private static Map <T1,T2> MY_MAP = new ConcurrentHashMap <T1,T2>();
这样就从变量级别的进行了并发控制,性能几乎不受什么影响。
2.除此之外我们还可以借助synchonized来进行线程同步,使得并发时线程锁定资源排队获取资源,这样能保证共享变量的多线程安全.具体实现方法如下:
private static Object MY_LOCK = new Object();
可以锁定一个方法 :
public synchonized(MY_LOCK) Map <T1,T2> getMyMap(){
...
}
但是如果你只是为了保护几个共享变量的话,没必要整个类同步,只要针对共享变量的操作进行同步即可
private static Map <T1,T2> MY_MAP = new HashMap <T1,T2>();
public Map <T1,T2> getMyMap(){
synchonized(MY_LOCK){
MY_MAP = appService.getMyMap();
}
...
}
3.类似于synchonized,java.utils.concurrent包下lock类也可以作为对象锁来使用,之前要导入java.utils.concurrent.locks.ReentrantLock类文件
private ReentrantLock myLock = new ReentrantLock();
public Map <T1,T2> getMyMap(){
myLock.lock();
try{
MY_MAP = appService.getMyMap();
}finally{
myLock.unlock();
}
...
}
这里需要注意的是,将需要锁住的模块放在 myLock.lock() 和myLock.unlock()语句之间,为了方便锁的释放,通常都将锁放在try{}最后一定要释放锁。
4.synchronized 和Lock的异同。主要相同点:Lock能完成Synchronized所实现的所有功能。主要不同点:Lock有比synchronied更精确的线程语义和更好的性能。Synchronized会自动释放所,而Lock一定要程序员手工释放,一般都在finally子句中释放。