0

我有两个线程,我目前正在使用同步块内的对象的 notify() 和 wait() 方法进行锁定。我想确保主线程永远不会被阻塞,所以我以这种方式使用了布尔值(仅提供了相关代码。)

//Just to explain an example queue
private Queue<CustomClass> queue = new Queue();

//this is the BOOLEAN
private boolean isRunning = false;

private Object lock;

public void doTask(){
       ExecutorService service = Executors.newCachedThreadPool();

            //the invocation of the second thread!!
            service.execute(new Runnable() {
                @Override
                public void run() {
                       while(true){
                            if (queue.isEmpty()){
                                synchronized (lock){
                                     isRunning = false;   //usage of boolean
                                     lock.wait();
                                }
                            }
                            else{
                                process(queue.remove());
                            } 
                       }
                });

}

//will be called from a single thread but multiple times.
public void addToQueue(CustomClass custObj){


       queue.add(custObj);
       //I don't want blocking here!!
       if (!isRunning){
           isRunning = true;      //usage of BOOLEAN!     
           synchronized(lock){
           lock.notify();
           }
       }
}

这里有什么问题吗?谢谢。 编辑: 目的:这样当 add() 将被第二次调用时,它不会在 notify() 上被阻塞。有没有更好的方法来实现主线程的这种非阻塞行为?

4

2 回答 2

0

队列未同步,因此上述代码可能会遭受条件变量和监视器典型的丢失唤醒呼叫。https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem 例如,这是一个有问题的序列:在运行开始时,Q 为空,isRunning 为假。线程 1 (t1) 检查 Q 是否为空(为真),然后停止运行。然后线程 2 (t2) 开始运行并执行 addToQ 方法。然后 t1 继续运行并等待锁,尽管 Q 不为空。如果您想要一个非阻塞解决方案,您可以使用 Java 提供的非阻塞 Q ( http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html)当然也可以使用java自带的blockingQueue,不过这是阻塞的。

于 2013-06-17T11:35:24.340 回答
0

尽管您没有显示addToQueue代码,但我相当肯定此代码将无法正常工作,因为您正在访问共享队列(它不是线程安全的)而没有任何同步。

process(queue.remove());

与其尝试使您的自定义队列工作(我怀疑您的布尔标志计划是否可行),不如节省时间和工作并使用JDK 中提供的BlockingQueuesConcurrentLinkedQueue之一。

于 2013-06-17T11:18:04.587 回答