关于多线程安全的一些解决方法

摘自: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子句中释放。

posted on 2013-12-31 17:00  Paul_bai  阅读(347)  评论(0编辑  收藏  举报

导航