简体   繁体   中英

Synchronized blocks and Locks

I have two threads and I am currently doing locking using an Object's notify() and wait() methods inside Synchronized blocks. I wanted to make sure that the main thread is never blocked so I used a boolean this way (only relevant code provided.)

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

Does anything seems wrong here? thanks. Edit: Purpose: This way when add() will be called the second time and more, it won't get blocked on notify(). Is there a better way to achieve this non blocking behavior of the main thread?

Although you do not show the addToQueue code I am fairly certain that this code will not work properly, as you are accessing the shared queue (which is not thread-safe) without any synchronization.

process(queue.remove());

Instead of trying to make your custom queue work (I doubt that your plan with the boolean flag is possible), save the time and work and use one of the BlockingQueues or ConcurrentLinkedQueue provided in the JDK.

The Queue is not synchronized and therefore the above code can suffer from the lost wake-up call typical for conditional variables and monitors. https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem For example, here is a problematic sequence: At the beginning of the run the Q is empty and isRunning is false. Thread 1 (t1) checks if Q is empty (which is true) and then stops running. Than Thread 2 (t2) starts running and execute the addToQ method. and then t1 continues running and waits on the lock although the Q is not empty. If you want a non-blocking solution you can use the non-blocking Q java is offering ( http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html)Of course, you can use java own blockingQueue, but this is blocking.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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