简体   繁体   English

线程未与单锁同步

[英]Thread not synchronized with single lock

I cannot properly synchronize this program, the result should be 0 in the second println too, because the two threads create and pop 10000 times each. 我无法正确同步该程序,第二个println中的结果也应该为0,因为两个线程各自创建并弹出10000次。 Do i have to synchronize in a different way ? 我是否必须以其他方式进行同步?

import java.util.*;

public class Main00 {

Queue<Integer> q = new PriorityQueue<Integer>();
Random rand = new Random();

public static void main(String[] args) {
    new Main00().doStuff();
}

public void doStuff(){
    Thread t1=new Thread(new Runnable(){
        public void run(){
            for(int i=0;i<10000;i++)produce();
        }
    });
    Thread t2=new Thread(new Runnable(){
        public void run(){
            for(int i=0;i<10000;i++)consume();
        }
    });

    System.out.println("Starting threads, q size is : "+q.size());
    t1.start();
    t2.start();

    try{
        t1.join();
        t1.join();
    }catch(InterruptedException e){}

    System.out.println("Ending threads, q size is : "+q.size());
}

synchronized public void produce() {
    q.add(rand.nextInt(100));
}

synchronized public void consume() {
    q.poll();
}

}

You're not joining the second thread: 您没有加入第二个线程:

    t1.join();
    t1.join();

Should be: 应该:

    t1.join();
    t2.join();

You're also using poll which doesn't block: 您还使用了不会阻止的poll

Retrieves and removes the head of this queue, or returns null if this queue is empty. 检索并删除此队列的头部,如果此队列为空,则返回null。

You may want to use PriorityBlockingQueue : 您可能要使用PriorityBlockingQueue

Multiple threads should not access a PriorityQueue instance concurrently if any of the threads modifies the queue. 如果任何线程修改了队列,则多个线程不应同时访问PriorityQueue实例。 Instead, use the thread-safe PriorityBlockingQueue class. 而是使用线程安全的PriorityBlockingQueue类。

You can utilize the take method to avoid busy-wait : 您可以利用take方法来避免忙碌

Retrieves and removes the head of this queue, waiting if necessary until an element becomes available. 检索并删除此队列的头,如有必要,请等待直到元素可用。

A call to poll does not necessarily consume an element. 进行poll的调用不一定会消耗一个元素。 If there is no element in the queue, it just returns null. 如果队列中没有元素,则仅返回null。

To make sure you effectively consume an element, you would write: 为了确保您有效地使用了元素,您可以编写:

  while(q.poll() == null);

Moreover, the class PriorityQueue is not threadsafe according to http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html . 此外,类PriorityQueue不是线程根据http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html You shoule use the thread-safe PriorityBlockingQueue class, which has a poll method that blocks with a timeout. 您应该使用线程安全的PriorityBlockingQueue类,该类具有poll方法,该方法会因超时而阻塞。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM