阻塞队列 - 是否需要客户端锁定?

时间:2017-10-16 02:02:52

标签: java multithreading producer-consumer blockingqueue

正如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();
        }
    }

}

问题:

在上面的代码中,

如何评估是否需要额外的客户端锁定?关键是复合行动......

0 个答案:

没有答案