CyclicBarrier、CountDownLatch、Semaphore的用法
CyclicBarrier、CountDownLatch、Semaphore的用法
CountDownLatch(线程计数器)
CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他n个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了
CyclicBarrier(回环栅栏-等待至barrier状态再全部同时执行)
字面意思回环栅栏,通过它可以实现让一组线程等待至某个状态之后再全部同时执行,叫做回环因为当所有线程都被释放以后,CyclicBarrier可以被重用。
Semaphore(信号量-控制同时访问的线程个数)
Semaphore翻译成字面意思为信号量,Semaphore可以控制同时访问的线程个数,通过acquire()获取一个许可,如果没有就等待,而release()释放一个许可。
CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同;CountDownLatch一般用于某个线程A等待若干个其它线程执行完任务之后执行;而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的。
Semaphore其实和锁有点类似,它一般用于控制对某组资源的访问权限。
volatile关键字的作用(变量可见性、禁止重排序)但不能保证原子性,它不是锁,只是类似锁的稍弱的同步机制
Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保变量的更新操作通知到其他线程。volatile变量具备两种特性,volatile变量不会被缓存在寄存器或者其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。
变量可见性
其一是保证该变量对所有线程可见,这里的可见性指的是当一个线程修改了变量的值,那么新的值对于
其他线程是可以立即获取的。
禁止重排序
volatile禁止了指令重排。
ThreadLocal作用(线程本地存储)
ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,ThreadLocal的作用提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。
ThreadLocalMap(线程的一个属性)
每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象。
将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中,然后在线程执行的各处通过这个静态ThreadLocal实例的get()方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦。
ThreadLocalMap其实就是线程里面的一个属性,它在Thread类中定义,
ThreadLocal.ThreadLocalMap threadLocals = null;
最常见的ThreadLocal使用场景为用来解决数据库连接、Session管理等。
ConcurrentHashMap并发,(分为了16个线程)
减小锁粒度:
减小锁粒度是指缩小锁定对象的范围,从而减小锁冲突的可能性,从而提高系统的并发能力,减小锁粒度是一种削弱多线程锁竞争的有效手段,这种技术典型的应用是ConcurrentHashMap(高性能的HashMap)类的实现。对于HashMap而言,最重要的两个方法是get与set方法,如果我们对整个HashMap加锁,可以得到线程安全的对象,但是加锁粒度太大。Segment的大小也被称为ConcurrentHashMap的并发度。
ConcurrentHashMap分段锁:
ConcurrentHashMap,它内部细分了若干个小的HashMap,称之为段(Segment)。默认情况
下一个ConcurrentHashMap被进一步细分为16个段,即就是锁的并发度。
如果需要ConcurrentHashMap中添加一个新的表项,并不是将整个HashMap加锁,而是首先根据hashCode得到该表项应该存放在哪个段中,然后对该段加锁,并完成put操作。在多线程环境中,如果多个线程同时进行put操作,只要被加入的表项不存放在同一个段中,则线程间可以做到真正的并行