2013-06-17 3 views
0

У меня есть два потока, и в настоящее время я выполняю блокировку с помощью методов 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() будет вызываться во второй раз и более, он не будет заблокирован при уведомлении(). Есть ли лучший способ добиться этого неблокирующего поведения основного потока?

+4

Хм, почему бы вам не использовать 'BlockingQueue '? – fge

+2

Пометка' isRunning' как 'volatile'. Доступ разрешен из двух потоков. –

+0

В чем проблема? –

ответ

0

Хотя вы не показываете код addToQueue, я вполне уверен, что этот код не будет работать должным образом, поскольку вы получаете доступ к общей очереди (которая не является потокобезопасной) без какой-либо синхронизации.

process(queue.remove()); 

Вместо того, чтобы пытаться сделать свою собственную работу очереди (я сомневаюсь, что ваш план с булевым флагом возможно), за исключение времени и работы и использовать один из BlockingQueues или ConcurrentLinkedQueue, предусмотренных в JDK.

+0

Код добавочного кода отображается. код процесса не отображается. –

+0

Да. Теперь я намерен использовать LinkedBlockingQueue. –

+0

Oi - позор на меня: Забыл прокрутить вниз в разделе кода. (. – Pyranja

0

Очередь не синхронизирована, поэтому приведенный выше код может пострадать от утерянного вызова пробуждения, характерного для условных переменных и мониторов. https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem Например, здесь есть проблемная последовательность: В начале пробега Q пуст, а isRunning - false. Резьба 1 (t1) проверяет, является ли Q пустым (это правда), а затем прекращает работу. Than Thread 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, но это блокировка.

Смежные вопросы