同步块和锁

时间:2013-06-17 10:35:06

标签: java locking nonblocking synchronized

我有两个线程,我正在使用同步块内的Object的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()阻塞。有没有更好的方法来实现主线程的这种非阻塞行为?

2 个答案:

答案 0 :(得分:0)

虽然您没有显示addToQueue代码,但我相当确定此代码无法正常工作,因为您在没有任何同步的情况下访问共享队列(不是线程安全的)。

process(queue.remove());

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

答案 1 :(得分:0)

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