java中基本的同步机制有synchronized,Lock等,这些机制可以实现并发任务共享一个资源时的同步操作。当实现一些较为复杂的并发任务时,可以使用一些同步辅助类来简化操作。
本节将介绍信号量(Semaphore),CountDownLatch辅助类。
信号量是一种计数器,用来保护一个或多个共享资源的访问。它是并发编程的一种基础工具,大多数编程语言都提供了这种机制。
CountDownLatch在完成一组正在其他线程中执行的操作之前,它允许线程一直等待。
1.Semaphore:
如果线程要访问一个共享资源,必须先获得信号量,信号量就是一个计数器,如果这个计数器为0,则代表这个线程将一只等待下去,直到计数器大于0,因为此时没有多余的资源可以使用。计数器大于0时,代表当前线程可以进行共享资源的访问,有可以使用的资源,因此线程将允许使用其中的一个资源。
当线程使用完某个计数器之后必须释放信号量,将计数器加1,以用来为其他线程提供多余的资源使用。否则信号量将不会被释放,也就时共享资源不会被其他线程再访问。
semaphore.acquire() 获取资源,即有访问权限,计数器减1.
semaphore.release() 释放资源,即访问结束时释放,计数器+1.
用来多个任务同时获取某类资源时进行同步访问,比如说有100份文档,3台打印机,让三台打印机轮流工作去进行打印,要防止文档出现混乱打印,就要同步地进行打印操作。每一个文档要用acquire()来获取资源,可以进行打印操作,阻止了其他文档的抢打。当文档打印完成后,调用release()释放资源,每个文档要监听3个打印机的状态,当有空闲的打印机时,立马获取资源进行打印。
2.CountDownLatch
也类似于一个计数器,当一个线程,要等待其他一个或者线程的一个或多个操作完成后再进行后续操作,可以使用CountDownLatch类,等待操作使用await() 方法,来进行等待监听。当其他线程完成一一组操作,调用countDown()方法,来通知等待线程它已经完成,此时计数器-1。当计数器为0的时候,await()等待结束,执行后续操作。
比如说一个签到会议系统,要等待所有人都到来才能开始会议,签到系统是一个线程,其他的人各自是一个线程,当会议准备好了,进行等待参与者签到时,调用await()方法,后面跟上后续操作。参与者签到这个动作是提醒了会议系统“我来了”,调用countDown()方法,计数器-1,当所有人(或者说会议的最大人数)都来到时,计数器为0,此时签到系统从等待状态变为开始状态,可以开始开会啦。