在多线程环境下我们日常使用的很多类都存在线程安全问题,比如
ArrayList、HashSet、HashMap,那么多线程环境下我们应该如何处理好线程问题?CAS算法是什么?除了synchronized有没有别的方法实现线程安全?乐观锁?悲观锁?
JUC工具包中针对这些日常开发中经常使用的集合类,给我们提供了线程安全的类来代替这些类。
- ArrayList
-->CopyOnWriteArrayList--写复制列表- HashSet
-->CopyOnWriteArraySet--写复制集合- HashMap
-->ConcurrentHashMap--分段锁映射
CopyOnWriteArrayList底层通过操作“副本”的形式避免并多线程环境下得并发问题。
当一个线程对
list进行操作时,会先加一把锁,然后将当前对象的值拷贝一份,重新创建一个长度+1的新对象,然后将引用地址指向新的ArrayList
add()方法源码
同
CopyOnWriteArrayList类似,只是底层存储数据的数据结构不同
源码
代码示例
ConcurrentHashMap底层将原始数据切分成一个一个小的segment,长度为2的n次方,然后分段加锁,多个线程同时处理,在保证安全的状态下也提升了一些效率。
原子性是指一个操作或多个操作要么全部执行,且执行的过程不会被任何因素打断,要么就都不执行。
Atomic包是JUC下得另一个专门为线程安全设计的Java包,包含多个原子操作类Atomic常用类
AtomicIntegerAtomicIntergerArrayAtomicBooleanAtomicLongAtomicLongArray
通过
synchronized关键字保证下载量在多线程下的累加安全。这里可以通过更加轻量级的方法,利用Atomic原子类完成优化。
优化代码
悲观锁
- 锁是用来做并发最简单的方式,当然其代价也是最高的。独占锁是一种 悲观锁,
synchronized就是一种 独占锁,它假设最坏的情况,并且只有在确保其它线程不会造成干扰的情况下执行,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。
乐观锁
- 所谓 乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。其中 CAS(比较与交换,
Compare And Swap) 是一种有名的无锁算法。
虽然基于 CAS的线程安全机制很好很高效,但要说的是,并非所有线程安全都可以用这样的方法来实现,这只适合一些粒度比较小型,如计数器这样的需求用起来才有效,否则也不会有锁的存在了。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70000430/viewspace-2789137/ ,如需转载,请注明出处,否则将追究法律责任。