取自:轻松使用线程: 减少争用(来自IBM developerWorks)清单 3. 一个减小锁的粒度的机会public class AttributesStore {
  private HashMap usersMap = new HashMap();
  private HashMap servicesMap = new HashMap();  public synchronized void setUserInfo(String user, UserInfo userInfo) {
    usersMap.put(user, userInfo);
  }  public synchronized UserInfo getUserInfo(String user) {
    return usersMap.get(user);
  }  public synchronized void setServiceInfo(String service, 
                                          ServiceInfo serviceInfo) {
    servicesMap.put(service, serviceInfo);
  }  public synchronized ServiceInfo getServiceInfo(String service) {
    return servicesMap.get(service);
  }
} 这里,用户和服务数据的访问器方法是同步的,这意味着它们在 AttributesStore 对象上同步。虽然这样做是完全线程安全的,但却增加了毫无实际意义的争用可能性。如果一个线程正在执行 setUserInfo ,就不仅意味着其它线程将被锁在 setUserInfo 和 getUserInfo 外面(这是我们希望的),而且意味着它们也将被锁在 getServiceInfo 和 setServiceInfo 外面。
以上来自IBM developerWorks。
如上面所说一个线程正在执行 setUserInfo ,那么其他线程都会被锁在另外三个函数外面,有点不理解,在函数前加synchronized,难道不仅仅锁住该函数吗?

解决方案 »

  1.   

    刚刚找楼主所说的原文看过了,文章已经很清楚的说明:楼主所举的代码是在AttributesStore的对象上进行同步。
    但因为该类中有两个属性,即usersMap与servicesMap,且这两个属性互相独立。这样一来,在整个对象上进行同步,显然是粗粒度的,增加了阻塞机会。如果分别对这两个对象进行线程同步处理,则不会出现“一个线程正在执行 setUserInfo ,那么其他线程都会被锁在另外三个函数外面”。而是“一个线程正在执行setUserInfo,那么其他线程就不能执行getUserInfo。但可以执行另外两个函数”这样可以减少50%机率的阻塞不知有没有说清楚,楼主可以再将原文看一遍
      

  2.   

    如上面所说一个线程正在执行 setUserInfo ,那么其他线程都会被锁在另外三个函数外面,有点不理解,在函数前加synchronized,难道不仅仅锁住该函数吗?
    ///
    当然啊,一个线程正在执行 setUserInfo ,那么其他线程都会被锁在另外三个函数外.
    这里的原因主要是同步方法前的synchronized不是"仅仅锁住该函数",而是锁住该函数所属的整个对象,这个对象中的synchronized方法都共享这把锁.看下面的代码你就明白了.public synchronized void setUserInfo(String user, UserInfo userInfo) {
        usersMap.put(user, userInfo);
      }相当于:public void setUserInfo(String user, UserInfo userInfo) {
        synchronized(this){ 
          usersMap.put(user, userInfo);
        }
      }//
      

  3.   

    hbyufan哥们讲的明白!!
    帮你顶了!!