如何保证集合是线程安全的?ConcurrentHashMap如何实现高效的线程安全?
问题:
- 如何保证集合是线程安全的?
- ConcurrentHashMap如何实现高效的线程安全?
知识点:
- 为什么需要ConcurrentHashMap?
Hashtable比较低效,所有线程公用同一把锁,效率低下。Collections工具类提供的Map方法,大同小异,源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| private static class SynchronizedMap<K, V> implements Map<K, V>, Serializable { private static final long serialVersionUID = 1978198479659022715L; private final Map<K, V> m; //划重点了,利用this作为互斥的mutex final Object mutex; private transient Set<K> keySet; private transient Set<Entry<K, V>> entrySet; private transient Collection<V> values; SynchronizedMap(Map<K, V> var1) { this.m = (Map)Objects.requireNonNull(var1); this.mutex = this; } SynchronizedMap(Map<K, V> var1, Object var2) { this.m = var1; this.mutex = var2; } public int size() { Object var1 = this.mutex; synchronized(this.mutex) { return this.m.size(); } } public boolean isEmpty() { Object var1 = this.mutex; //方法不再申明为synchronized方法,但是利用this作为互斥的mutex,大同小异 synchronized(this.mutex) { return this.m.isEmpty(); } }
|
高并发时候,容易始HashMap死循环导致CPU占用100%。可参考不正当使用HashMap导致cpu 100%的问题追究,
HashMap 死循环的探究
- ConcurrentHashMap,篇幅太长,后续有专门文章分析。
回答问题
Java提供了不同层面的线程安全支持,在传统的框架内部,除了Hashtable等同步容器,还提供了所谓的同步包装器,我们可以调用Collecions工具的同步方法,来获取一个同步的包装容器(如:Collections.synchronizedMap),但是他们都是利用非常粗粒度的处理方式,在高并发的时候,性能比较低下。
另外,更加普遍的选择是利用并发包提供的线程安全容器类,它提供了:
具体保证线程安全的方式,包括从有简单的synchronize方式,到基于更加精细化的,比如基于分离锁实现的ConcurrentHashMap等并发实现等。具体选择要看开发的场景需求。总得来说,并发包提供的容器通用场景,远优于早期的简单的同步实现。
自己项目中使用代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| private Map<Promise, ReadableMap> mPictureTakenOptions = new ConcurrentHashMap<>(); private Map<Promise, File> mPictureTakenDirectories = new ConcurrentHashMap<>(); public void takePicture(ReadableMap options, final Promise promise, File cacheDirectory) { mPictureTakenPromises.add(promise); mPictureTakenOptions.put(promise, options); mPictureTakenDirectories.put(promise, cacheDirectory); if (mPlaySoundOnCapture) { MediaActionSound sound = new MediaActionSound(); sound.play(MediaActionSound.SHUTTER_CLICK); } try { super.takePicture(); } catch (Exception e) { mPictureTakenPromises.remove(promise); mPictureTakenOptions.remove(promise); mPictureTakenDirectories.remove(promise); throw e; } }
|
参考:
声明:此为原创,转载请联系作者
作者:微信公众号添加公众号-遛狗的程序员 ,或者可以扫描以下二维码关注相关技术文章。
当然喜爱技术,乐于分享的你也可以可以添加作者微信号: