正如Java_author所述:
5.1.1。同步集合的问题
同步集合是线程安全的,但有时您可能需要使用额外的客户端锁定来保护复合操作。
示例 - 多个生产者/消费者问题:
Algorithm对使用线程不安全缓冲区的多个生产者消费者使用忙等待方法,需要,
global RingBuffer queue; // A thread-unsafe ring-buffer of tasks.
global Lock queueLock; // A mutex for the ring-buffer of tasks.
但是下面的代码运行忙等待(while(true){..}
)算法使用线程安全缓冲区(queue
),没有锁定,
/* NumbersProducer.java */
package responsive.blocking.prodcons;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadLocalRandom;
public class NumbersProducer implements Runnable{
private BlockingQueue<Integer> numbersQueue;
private final int poisonPill;
private final int poisonPillPerProducer;
public NumbersProducer(BlockingQueue<Integer> numbersQueue, int poisonPill, int poisonPillPerProducer) {
this.numbersQueue = numbersQueue;
this.poisonPill = poisonPill;
this.poisonPillPerProducer = poisonPillPerProducer;
}
@Override
public void run() {
try {
generateNumbers();
}catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void generateNumbers() throws InterruptedException{
for(int i=0; i < 100; i++) {
numbersQueue.put(ThreadLocalRandom.current().nextInt(100));
}
for(int j=0; j < poisonPillPerProducer; j++) {
numbersQueue.put(poisonPill);
}
}
}
/* NumbersConsumer.java */
package responsive.blocking.prodcons;
import java.util.concurrent.BlockingQueue;
public class NumbersConsumer implements Runnable{
private BlockingQueue<Integer> queue;
private final int poisonPill;
public NumbersConsumer(BlockingQueue<Integer> queue, int poisonPill) {
this.queue = queue;
this.poisonPill = poisonPill;
}
public void run() {
try {
while(true) {
Integer number = queue.take();
if(number.equals(poisonPill)) {
return;
}
System.out.println(Thread.currentThread().getName() + " result: " + number);
}
}catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
/* Driver.java */
package responsive.blocking.prodcons;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class Driver {
public static void main(String[] args) {
int BOUND = 10;
int nProducers = 4;
int nConsumers = Runtime.getRuntime().availableProcessors();
int poisonPill = Integer.MAX_VALUE;
int value = 1;
int poisonPillPerProducer = ((value = nConsumers / nProducers) < 1)?1:value;
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(BOUND);
for(int i =0; i< nProducers; i++) {
new Thread(new NumbersProducer(queue, poisonPill, poisonPillPerProducer)).start();
}
for(int j=0;j < nConsumers; j++ ) {
new Thread(new NumbersConsumer(queue, poisonPill)).start();
}
}
}
问题:
在上面的代码中,
如何评估是否需要额外的客户端锁定?关键是复合行动......