0. Collections.synchronizedXxx()

Java 中常用的集合框架中的实现类:HashSet/TreeSet、ArrayList/LinkedList、HashMap/TreeMap 都不是线程安全的。即如果存在多个线程访问它们,并且有超过一个的线程试图修改它们,便存在线程安全的问题:

Collection c = Collections.synchronizedCollection(new ArrayList());
List list = Collections.synchronizedList(new ArrayList());
Set s = Collections.synchronizedSet(new HashSet());
Map m = Collections.synchronizedMap(new HashMap());

1. 注意

使用 java.util.concurrent.*下的类并非万事大吉

ConcurrentHashMap、synchronized与线程安全

使用 hashmap 做字符串的次数统计,为保证容器的线程安全,在修改容器内容时,加锁,在java中即是通过 synchronized 的关键字实现加锁。

public class ConcurrentMapTest
{
    private HashMap<String, Integer> map = 
            new HashMap<>();

    public synchronized void add(String key)
    {
        Integer value = map.get(key);
        if (value == null)
        {
            // 也可通过 map.containsKey(key) 进行判断
            map.put(key, 1);
        }
        else
        {
            map.put(key, value+1);
        }
    }
}

如果我们使用 ConcurrentHashMap 是不是就可以避免 synchronized 关键字的使用了呢?

public class ConcurrentMapTest
{
    private ConcurrentHashMap<String, Integer> map = 
            new ConcurrentHashMap<>();

    public void add(String key)
    {
        if (!map.containsKey(key))
        {
            map.put(key, 1);
        }
        else
        {
            map.put(key, map.get(key)+1);
        }
    }
}

注意,map.put(key, map.get(key)+1) 实际上执行了至少三个原子操作:

  • map.get
  • value + 1
  • map.put

因此其 add 方法仍需被 synchronized 关键字修饰。

posted on 2017-11-18 23:05  未雨愁眸  阅读(534)  评论(0编辑  收藏  举报