日期:2014-05-20  浏览次数:20710 次

synchronized 的问题
Java code

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 外面。

而且意味着它们也将被锁在 getServiceInfo 和 setServiceInfo 外面。 为甚麽会这样呢
,是方法锁 而不是对象锁


原文 http://www.ibm.com/developerworks/cn/java/j-threads/index2.html

------解决方案--------------------
方法锁和对象锁,没听说过这个概念。
楼主,例子中的synchronized 关键字,它的锁,是所在具体AttributesStore类的一个实例上面的。

加锁的目的,是为了保护两个内置对象usersMap 和servicesMap 的线程安全。

优点:无论调用对象的哪个方法,受保护的2个内置对象,它的数据都会是一致的。
缺点:由于两个内置对象使用了同一个锁,那么,你在访问其中一个对象的同时,
其它线程是无法访问另一个对象的。

“被所在 ... 外面”就是上述的缺点。
------解决方案--------------------
楼上preferme已经说的好了。

我在这里再赘述一下。

首先,所有的锁都是加载对象上的。

即使是同步方法也是如此,只不过同步方法是锁的this

相当于
Java code

public void synchronized deal(){
    synchronized(this) {
        //代码块
    }
}

------解决方案--------------------
探讨

楼上preferme已经说的好了。

我在这里再赘述一下。

首先,所有的锁都是加载对象上的。

即使是同步方法也是如此,只不过同步方法是锁的this

相当于
Java code

public void synchronized deal(){
synchronized(this) {
//代码块
}
}




如果一个线程获取了某个……

------解决方案--------------------
对象锁的概念,就是这个锁是属于这个当前对象的,某个线程调用同步方法,就必须获得这个对象的锁,而每个对象只拥有一把锁,所以当有线程获得当前对象的锁时,其他线程都得等待获得锁的线程释放这个对象的锁,即在锁池中等待。