1、semaphore
Semaphore中文解释成信号量的意思,可以看成一个可获数量有限的共享锁。锁只可被有限数量线程使用。
这个辅助类的核心方法是acquire以及release方法。acquire方法用于获取许可,release用于归还一个许可。
acquire方法其默认调用的是非公平的获取方法。意思也就是每当执行一次这个acquire方法,便会将你指定的avaliable(你指定的数量的许可证)减1。并将剩余的许可证数量利用CAS算法设置为还可获取到的avaliable数量。随后返回这个剩余数量。这里用到了一个无限for循环用于保证线程安全。这个获取许可证的操作是没有“上锁”的。故而利用这个无限循环+CAS的形式便可以确保当多个线程获取许可的时候,造成的avaliable不一致的情况。
final int nonfairTryAcquireShared(int acquires) { for (;;) { int available = getState(); int remaining = available - acquires; if (remaining < 0 || compareAndSetState(available, remaining)) return remaining; } } 非公平锁也就是说线程获取锁的顺序是不一定的。而公平锁是按照先来后到的顺序获取锁。 acquire方法是一个阻塞式的,其内部使用类无限循环以及locksupport去持续获取许可,当获取不到时会调用park方法阻塞线程。 还有tryAcquire方法,这个方法的意思跟trylock类型,意思就是获取不到就返回false去做别的事情。 release方法:释放许可。 注意在调用release方法之前不一定要调用acquire方法。 使用场景:我们一般使用信号量来限制访问资源的线程数量,比如说篮球场五个最多被使用。则如下:
for(int x = 0;x<12;x++) { new Thread(new Runnable() { @Override public void run() { try { semaphore.acquire(); System.out.println("班级" + Thread.currentThread() + "正在篮球场 踢球"); Thread.sleep(3000); System.out.println("班级" + Thread.currentThread() +" 结束踢球"); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }
那这个信号量Semaphore和Reentranlock的区别。 首先这个lock方法一定要先于unlock方法执行。如若不然会运行时异常 java.lang.IllegalMonitorStateException。但是Semaphore可以允许非owner线程执行其他线程的锁操作。 随后Semaphore可以通过非owner的线程来实现死锁恢复,但Lock则做不到。要使用Lock.unlock()来释放锁,首先你得拥有这个锁对象,因此非owner线程(事先没有拥有锁)是无法去释放别的线程的锁对象
Exchanger:这个辅助类可以看成是双向数据传输的SynchronousQueue。即没有消费者生产者之分,任意两个线程可以交换数据。 核心方法是:exchange.
CyclicBarrier:只允许一组线程彼此等待,直到所有线程到达指定集合点。 CountDownLatch:导游线程等待其他线程到达。 这两个的区别在于:(摘自博主https://www.cnblogs.com/kexianting/p/8566318.html)
CountDownLatch | CyclicBarrier |
减计数方式 | 加计数方式 |
计算为0时释放所有等待的线程 | 计数达到指定值时释放所有等待线程 |
计数为0时,无法重置 | 计数达到指定值时,计数置为0重新开始 |
调用countDown()方法计数减一,调用await()方法只进行阻塞,对计数没任何影响 | 调用await()方法计数加1,若加1后的值不等于构造方法的值,则线程阻塞 |
不可重复利用
那具体到底这两个是如何使用的呢? CountDownLatch可以看作是一个倒计时装置。 例如:主线程就是一个司机,那其他待执行的线程就相当于乘客。CountDownLatch的数量就相当于是车上的座位。乘客一个个上车直到全部坐满。 static CountDownLatch countDownLatch = new CountDownLatch(20); static class Passenger extends Thread { @Override public void run() { synchronized (CountDownLatch.class) { System.out.println("乘客" + Thread.currentThread() + "上车"); countDownLatch.countDown(); System.out.println("车上还剩"+countDownLatch.getCount()); } } } public static void main(String[] args){ for(int x = 0;x<23;x++){ new Passenger().start(); } try { countDownLatch.await(); System.out.println("客车已满,司机发车!!"); } catch (InterruptedException e) { e.printStackTrace(); } }
而CyclicBarrier可以看成是一个障碍,只有所有的人齐心协力才可以共同越过这个障碍。 | 可重复利用 |