方法中加锁的不同

现有如下代码,为什么getStatsMap1这个不能锁住,而getStatsMap2是可以的,这2者有什么区别,高手帮解释下,谢谢。

依据我的理解,对一个static 变量加锁和对方法加锁应该是效果一样

class TestThread {

private static Map<String, String> statsMap = null;

public Map<String, String> getStatsMap1() {
    synchronized (statsMap) {
        if (statsMap == null) {
            statsMap = getAllTable();
        }
    }
    return statsMap;
}

public synchronized Map<String, String> getStatsMap2() {
    if (statsMap == null) {
        statsMap = getAllTable();
    }
    return statsMap;
}

private Map<String, String> getAllTable() {
    Map<String, String> map = new HashMap<String, String>();
    map.put("user", "user");
    return map;
}

}

两个方法锁定的资源不一样。在方法上同步,相当于实例的加锁。
getStatsMap2的代码相当于:
[code="java"]
public Map getStatsMap2() {
synchronized(this){
if (statsMap == null) {
statsMap = getAllTable();
}
return statsMap;
}
}
[/code]
方法1在竞争 statsMap 时会被锁上。但是:statsMap 的初始值为null,代码执行会报错的。

在静态方法上加锁,那么锁的就是类,也就是TestThread.class。
在实例方法上加锁,那么锁的就是对象,也就是TestThread的一个实例。

因为锁的不一样,一个是类,一个是对象,所以这两个方法之间是没有竞争关系的。

你这里是要在静态方法和实例方法中都要去操作一个静态变量statsMap,那么就应该在statsMap上加锁,也就是:synchronized (statsMap) {...},否则就根本达不到效果了。