1.给出同步器的定义
同步器指的是控制通用同步方法的类
2.描述倒计时门闩(CountDownLatch)的行为
倒计时门闩会导致一条或者多条线程在"门口"一直等待直到另一条线程打开这扇门, 线程才得以继续运行
它是由一个计数变量和两个操作组成的,这两个操作分别是"导致一条线程等待直到计数变为0" 以及"递减计数变量"
3.当调用CountDownLatch的void countDown()方法且计数变为0时会发生什么呢
释放所有等待线程
4.描述同步屏障的行为
同步屏障允许一组线程彼此互相等待,直至抵达某个公共的屏障点
因为该屏障在等待线程被释放之后可以重用,所以称它为可循环使用的屏障
该同步器对于这类数量固定,并且互相之间必须不时等待彼此的多线程应用很有用
5.判断对错:任意线程等待时屏障被重置或者在调用await()方法时屏障被打破,则CyclicBarrier的int await()方法返回-1
错
当有线程正在等待时该同步屏障被重置了(通过reset()方法)以及当同步屏障在await()方法被调用或者任意线程正在等待时同步屏障被打破,CyclicBarrier的int await()方法就会抛出java.util.concurrent.BrokenBarrierException
6.描述一个交换器的行为
交换器提供一个线程彼此之间能够交换对象的同步点
每条线程都会往这个交换器的exchange()方法传入一些对象,匹配伙伴线程,同时接收伙伴线程中的对象作为返回值
7.Exchanger的V exchange(V x)方法完成了什么操作
Exchanger的V exchange(V x)会在这个交互点上等待其他线程到达(除非调用线程被中断了),之后将所给对象传入其中,接收其他线程的对象作为返回
8.描述一个信号量的行为
信号量维护了一组许可证(permit),以约束访问被限制资源的线程数
当没有可用的许可证时,线程的获取尝试会一直阻塞,直到其他的线程释放一个许可证
9.指出两种类型的信号量
信号量有两种类型,分别是计数信号量(当前值可以被递增加1)和二进制信号量或者互斥信号量(当前值只能取0或1)
10.描述一个phaser的行为
phaser是一个更加弹性的同步屏障
和同步屏障一样,一个phaser使得一组线程在屏障上等待,在最后一条线程到达之后,这些线程得以继续执行
phaser也提供barrierAction的等价操作
和同步屏障协调固定数目的线程不同,一个phaser能够协调不定数目的线程,这些线程可以在任何时候注册
为了实现这一功能,phaser使用了phase和phase值
11.Phaser的int register()方法返回什么
类Phaser的int register()方法返回用于分类抵达的phase值
如果这个值是负数,该phaser就会终止,此时注册不产生任何影响
这个数值称为抵达phase值
12.清单3-2(第3章中)展示一个改良版的PC程序
重新使用Semaphore处理同步来创建这一应用程序
import java.util.concurrent.Semaphore;
public class PC {
public static void main(String[] args) {
Shared shared = new Shared();
Semaphore semaphoreConsumer = new Semaphore(0);
Semaphore semaphoreProducer = new Semaphore(1);
new Producer(shared, semaphoreProducer, semaphoreConsumer).start();
new Consumer(shared, semaphoreProducer, semaphoreConsumer).start();
}
}
class Shared {
private char c;
public char getSharedChar() {
return c;
}
public void setSharedChar(char c) {
this.c = c;
}
}
class Producer extends Thread {
private Shared shared;
private Semaphore semaphoreProducer, semaphoreConsumer;
public Producer(Shared shared, Semaphore semaphoreProducer, Semaphore semaphoreConsumer) {
this.shared = shared;
this.semaphoreProducer = semaphoreProducer;
this.semaphoreConsumer = semaphoreConsumer;
}
@Override
public void run() {
for (char ch = 'A'; ch <= 'Z'; ch++) {
try {
semaphoreProducer.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
shared.setSharedChar(ch);
System.out.println(ch + " produced by producer.");
semaphoreConsumer.release();
}
}
}
class Consumer extends Thread {
private Shared shared;
private Semaphore semaphoreProducer, semaphoreConsumer;
public Consumer(Shared shared, Semaphore semaphoreProducer, Semaphore semaphoreConsumer) {
this.shared = shared;
this.semaphoreProducer = semaphoreProducer;
this.semaphoreConsumer = semaphoreConsumer;
}
@Override
public void run() {
char ch;
do {
try {
semaphoreConsumer.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
ch = shared.getSharedChar();
System.out.println(ch + " consumed by consumer.");
semaphoreProducer.release();
} while (ch != 'Z');
}
}