2016-07-03 4 views
2

Я пишу этот класс, который имитирует барьерную точку. Когда нить достигает этой точки барьера, она не может продолжаться до тех пор, пока другие нити не достигнут этой точки. Я использую счетчик, чтобы отслеживать количество потоков, которые достигли этого момента. Предположим, что класс ожидает N + 1 потоков, но ему заданы только N потоков. В этом случае программа будет поддерживать все потоки ожидания, потому что она думает, что еще есть еще один поток.Бесплатно все ожидаемые темы

Я хочу написать метод, который позволит мне освободить все ожидающие потоки независимо от того, думает ли программа, что еще есть потоки, чтобы добраться до точки барьера.

Моя программа ждать для всех потоков,

public volatile int count; 
public static boolean cycle = false; 

public static Lock lock = new ReentrantLock(); 
public static Condition cv = lock.newCondition(); 

public void barrier() throws InterruptedException { 
    boolean cycle; 
    System.out.println("lock"); 
    lock.lock(); 
    try { 
     cycle = this.cycle; 
     if (--this.count == 0) { 
      System.out.println("releasing all threads"); 
      this.cycle = !this.cycle; 
      cv.signalAll(); 
     } else { 
      while (cycle == this.cycle) { 
       System.out.println("waiting at barrier"); 
       cv.await(); // Line 20 
      } 
     } 
    } finally { 
     System.out.println("unlock"); 
     lock.unlock(); 
    } 
} 

Я думал, что я мог бы просто создать метод, который вызывает метод signalAll() и все потоки будут свободными. Однако проблема заключается в том, что если программа ожидает больше потоков, она будет поддерживать блокировку, потому что она будет ждать по строке 20.

Есть ли способ обойти эту блокировку? Как мне подойти к этой проблеме?

+0

'this.cycle = this.cycle; cv.signalAll(); '? – immibis

+0

Если это многоразовый барьер, вам также нужно решить, что должно произойти с потоками, которые появляются после вашего бесплатного звонка, и freeAll необходимо перезагрузить this.count. – immibis

ответ

0

Лучше идея - использовать стандартный java.util.concurrent примитивный - CyclicBarrier методом 'перезагрузки':

/** 
* Resets the barrier to its initial state. If any parties are 
* currently waiting at the barrier, they will return with a 
* {@link BrokenBarrierException}. Note that resets <em>after</em> 
* a breakage has occurred for other reasons can be complicated to 
* carry out; threads need to re-synchronize in some other way, 
* and choose one to perform the reset. It may be preferable to 
* instead create a new barrier for subsequent use. 
*/ 
public void reset() 
Смежные вопросы