一、一般模式下线程安全的HashMap

  默认情况常用的HashMap都是线程不安全的,在多线程的环境下使用,常常会造成不可预知的,莫名其妙的错误。那么,我们如何实现一个线程安全的HashMap呢?其中一个可行的方式是使用Collectons.synchronizedMap() 方法来包装我们的HashMap。如下:

Map<String, String> map = Collections.synchronizedMap(new HashMap<String,String>());

  

Collections.synchronizedMap()会生成一个SynchronizedMap,它使用委托模式,将自己HashMap相关的功能交给传入HashMap实现,二自己负责线程安全的相关实现,下面看看
SynchronizedMap的定义:
    private static class SynchronizedMap<K,V>
implements Map<K,V>, Serializable {
private static final long serialVersionUID = 1978198479659022715L; private final Map<K,V> m; // Backing Map // 使用 mutex 实心对 map 的互斥操作
final Object mutex; // Object on which to synchronize SynchronizedMap(Map<K,V> m) {
this.m = Objects.requireNonNull(m);
mutex = this;
}

  如在代码中看到的,所有对Map的操作都需要用 这个 mutex  来同步,以实现线程安全。比如说下面这些常见的对HashMap的操作方法:

        public boolean containsKey(Object key) {
synchronized (mutex) {return m.containsKey(key);}
}
public boolean containsValue(Object value) {
synchronized (mutex) {return m.containsValue(value);}
}
public V get(Object key) {
synchronized (mutex) {return m.get(key);}
}

  除了以上看到的方法之外,其他的Map相关的方法有类似的操作。虽然这个包装的Map可以实现线程安全的要求,但是,它在多线程环境下的性能表现并不是很好,无论是对Map的读取还是写入,偶数需要获得 mutex 的同步锁,这会导致所有对Map的安全操作也会进入等待状态,知道mutex可用。 如果并发级别不高,那么这个 包装的Map可以基本满足要求,但是在搞并发的环境中,我们需要寻找新的解决方案。 ——---> 那就是我们的 ConcurrentHashMap.

二、提高"锁"性能的策略

  1. 减少锁的持有时间

    只在必要时进行同步,减少锁的持有时间。比如说在一个方法中只有一个变量需要同步,那么就没有必要对这整个方法都进行同步,而只需要同步这个变量即可。

        // 无谓的加锁时间
public synchronied void syncMethod() { othrerMethod();
mutexMethod();
otherMethod();
} // 正确的加锁时间
public void syncMethod() { othrerMethod();
synchronied(this){
mutexMethod();
}
otherMethod();
}

  2.  减小锁的粒度

    在获取全局信息方法不频繁的时候,通过减小锁的粒度可以搞系统的吞吐量。

  3. 读写分离锁替换独占锁

    在读都写少的情况下,使用读写分离锁,多线程读时不阻塞,而只对写线程进行同步。

  4. 锁分离

    对不同功能的锁进行不同的锁策略。

  5. 锁粗化

    系统对于"锁"的调度也是需要性能消耗的,又是我们可以适当的加大锁的范围,比如说在循环中尽量减少对锁的请求和释放,而是在得到锁的情况,一次性把问题解决。

  

最新文章

  1. Java是如何处理别名(aliasing)的
  2. [转]Java 征途:行者的地图
  3. 技术英文单词贴--E
  4. 揭开HTTP网络协议神秘面纱系列(一)
  5. 在magento中使用正则式
  6. matlab最小二乘法数据拟合函数详解
  7. python 列表、字典的方法
  8. Main Thread Checker 问题解决
  9. js初级练习
  10. 4-21 嵌套选择器 、块级元素和内联元素、光标、布局-overflow
  11. CRM WEB UI 01 BOL向导创建的搜索
  12. 开发者用的linux系统推荐
  13. 你真的了解word-wrap和word-break的区别吗? (转载)
  14. struts2(二)值栈 threadlocal ogal ui
  15. 黄聪:PHP Ajax 跨域问题最佳解决方案
  16. 利用url传多个参数
  17. 12、利用docker快速搭建Wordpress网站
  18. 关于HFile的存储结构梳理以及快速定位rowkey
  19. bzoj 4573 大森林
  20. select * from 为什么效率低?

热门文章

  1. git rm简介
  2. java5 Condition用法--实现线程间的通信
  3. __sync_fetch_and_add系列
  4. libevent源码深度剖析十
  5. javac老提示无效的标记
  6. 在aspx页面中使用三元表达式
  7. GO程序设计2——面向过程基础知识
  8. SpringMVC——处理 JSON:使用 HttpMessageConverter
  9. 在Global.asax文件的Application_BeginRequest中获取request请求内容
  10. UIWebView分页显示