线程安全(二)-同步工具类

同步工具类:

 

1闭锁:

闭锁的作用相当于一扇门:在闭锁到达结束状态之前,这扇门一直是关闭的,并且没有任何线程能通过。

当闭锁到达结束状态后,将不会再改变状态,因此这扇门将永远保持打开状态,闭锁可以用来确保某些活动指导其他活动都完成后才继续执行。

 

例如;

1确保某个计算在其需要的所有资源都被初始化之后才继续执行。

2确保某个服务在其依赖的所有其他服务都已经启动之后才启动。

3 等待指导某个操作的所有参与者都就绪后再继续执行。

 

CountDownLatch是一种灵活的闭锁实现,它可以使一个或多个线程等待一组事件发生。闭锁状态包括一个计数器,该计数器被初始化一个整数,表示需要等待的事件数量。countDown方法递减计数器,表示有一个事件已经发生了,而await方法等待计数器达到零,这表示所有需要等待的事件都已经发生,如果计数器的值为非零,那么await会一直阻塞直到计数器为零,或者等待中的线程中断,或者等待超时。

 

FutureTask也可以用作闭锁。

 

Future.get行为取决于任务的状态,如果任务已经完成,那么get立即返回结果,否则get将进入阻塞状态,直到任务完成。

 

信号量:

 

计数星好亮(CountingSemaphore) 用来控制同时访问某个特定资源的操作数量,或者同时还行某个指定操作的数量,计数信号量还可以用来实现某种资源池对容器加入边界。

 

Semaphore中管理这儿一组虚拟的许可,许可的初始数量可以通过构造函数来指定执行操作时可以首先获得许可,并在使用后释放许可,或者知道被中断和超时。

 

 

栅栏:CyclicBarrier

栅栏类似于闭锁,它能阻塞一组线程知道某个事件发生。栅栏与闭锁的关键区别在于,所有的线程必须同时道道栅栏位置,才能继续执行。闭锁用于等待事件,而栅栏用于等待其他线程,栅栏用于实现一些协议,例如几个家庭决定在某个地方集合:“所有人6:00在麦当劳碰头,到了以后要等其他人,之后在讨论下一步要做的事情”。

 

CyclicBarrier可以使一定数量的参与方反覆地在栅栏位置汇集,它在并行迭代算法中非常有用:这种算法将一个问题拆分成一系列相互独立的子问题。当线程道道栅栏位置将调用await方法,这个方法将阻塞直到所有线程都到达栅栏位置。如果所有线程都到达了栅栏位置,那么栅栏打开,所有线程将打开,此时所有线程都被释放,而栅栏将被重置以便下次使用。

 

如果对await超时,或者await阻塞的线程被中断,那么栅栏就 被认为打破了,所有阻塞的await调用都将被终止并抛出brokenBarrierException。如果成功地通过栅栏,那么await将为每个线程返回一个唯一的到达索引号,我们可以利用这些索引来选举产生一个领导线程,并在下一次迭代中有该领导线程执行一些特殊的工作。

 

 

另一种形式的栅栏是Exchanger它是一个两方栅栏,各方在栅栏位置上交换数据,当两方执行部队称操作时,Exchanger会非常有用,例如当一个线程想缓冲区写入数据,而当另一个线程熊缓冲区读取数据,这些线程可以使用Exchanger来回和,并将满的缓冲区与空的缓冲区交换。当两个线程通过Exchanger交换对象时这种交换就把这两个对象安全地发布给另一方。

它的基本思想类似于一个插线板维护很多插槽,用来提高性能,在通过动态哈希表来映射不同的插槽。

这个插槽是一个节点的参照。这个节点包括一个对象,以及等待被唤醒的一个县城。

如果传入的占领县城看到插槽式空的,它会比较并设置一个节点并等待下一个县城的调用。第二个充实县城看到插槽是非空的,它比较这个节点是否属于期望的对象,如果是则设置改节点为空,然后把该线程带有的对象返回给节同时唤醒这个节点的等待线程。

 

 

小结:

尽量将域声明为final类型,除非他们是可变的。

不可变对象一定是线程安全的

封装有助于管理复杂性。

用锁来保护每个可变变量

当保护同一个不变形条件中的所有变量时,要使用同一个锁。

执行符合操作期间要持有锁。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值