Возобновление всех потоков в состоянии ожидания, используя только метод уведомления - PullRequest
1 голос
/ 08 марта 2020

Я хочу возобновить все потоки, которые переходят в состояние ожидания, используя только метод уведомления. Я не хочу использовать notifyAll () для возобновления всех потоков в состоянии ожидания.

public class MultithreadingTest{
    public static void main(String[] args) throws  Exception{
        SharedResource sr = new SharedResource();
        sr.isWaiting = true; // to make thread to go in waiting state
        Thread t1 = new Thread(sr);
        Thread t2 = new Thread(sr);
        Thread t3 = new Thread(sr);
        t1.start();
        t2.start();
        t3.start();
        sr.isWaiting = false; // to directly call the notify() based on condition
        Thread t6 = new Thread(sr);
        t6.start();
    }
}

class SharedResource implements Runnable{
    volatile boolean isWaiting;
    public void run(){
        System.out.println(Thread.currentThread().getName() + " enters with status " + this.isWaiting);
        synchronized (this){
            try {
                if(this.isWaiting) {
                    System.out.println(Thread.currentThread().getName() + " goes into waiting stage");
                    wait(); // Release the lock so other threads can acquire it
                    System.out.println(Thread.currentThread().getName() + " wakes up");
                } else {
                    System.out.println(Thread.currentThread().getName() + " calling the notify method");
                }
                notify(); // Notifying the random thread which is in waiting state to resume again
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Вызов wait () снимет блокировку intrinsi c, чтобы другие потоки в очереди можете его приобрести. Я хочу, чтобы последний поток напрямую вызвал функцию notify (), которая уведомит любой из потоков, находящихся в состоянии ожидания, для возобновления. Ожидающий поток просыпается и вызывает notify (), который снова возобновит работу потока в состоянии ожидания.

1 Ответ

1 голос
/ 08 марта 2020

В этом примере мы хотим, чтобы эти действия происходили в следующем порядке:

  • порождает поток T1, T2 и T3 и переводит все три в спящий режим на общем ресурсе
  • изменить флаг volatile и spawn T4
  • T4 входит в критическую секцию, пробуждает один спящий поток, а затем выходит
  • после получения уведомления, каждый поток уведомляет ровно один раз и затем выходит

Приведенный выше код является почти правильным, но поскольку метод main выполняется "основным" потоком, мы должны убедиться, что потоки T1, T2, T3 go находятся в состоянии ожидания до нерестовая нить T4. Мы можем сделать это, используя семафор. Поток main будет блокироваться при вызове semaphore.acquire() до тех пор, пока все потоки не будут в правильном состоянии.

Примечание , что из-за гонки, в приведенном выше коде поток T1 может войти в критической секции после флаг установлен в ложь - поэтому мы потеряем контроль над порядком действий.

См. код обновления ниже, он выведет что-то вроде

main thread starts
Thread-2 enters with status true
Thread-2 goes into waiting stage
Thread-1 enters with status true
Thread-1 goes into waiting stage
Thread-0 enters with status true
Thread-0 goes into waiting stage
Thread-3 enters with status false
Thread-3 calling the notify method
Thread-3 terminates
main thread terminates
Thread-2 wakes up
Thread-2 terminates
Thread-1 wakes up
Thread-1 terminates
Thread-0 wakes up
Thread-0 terminates

код

package sample;

import java.util.concurrent.Semaphore;

public class MultithreadingTest {
  public static void main(String[] args) throws Exception {
    System.out.println("main thread starts");
    SharedResource sr = new SharedResource();
    // to make thread to go in waiting state
    sr.isWaiting = true;
    Thread t1 = new Thread(sr);
    Thread t2 = new Thread(sr);
    Thread t3 = new Thread(sr);
    t1.start();
    t2.start();
    t3.start();

    // let the main thread wait, until all 3 threads reach the checkpoint
    sr.numWaiting.acquire(3);
    sr.isWaiting = false; // to directly call the notify() based on condition
    Thread t6 = new Thread(sr);
    t6.start();
    System.out.println("main thread terminates");
  }
}

class SharedResource implements Runnable {
  // keep a count of how many threads entered the critical section
  // needed by the main thread to know when to start the "wake-up" thread
  Semaphore numWaiting = new Semaphore(0);
  volatile boolean isWaiting;

  public void run() {
    System.out.println(Thread.currentThread().getName() + " enters with status " + this.isWaiting);
    synchronized (this) {
      try {
        if (this.isWaiting) {
          System.out.println(Thread.currentThread().getName() + " goes into waiting stage");
          numWaiting.release(1);
          wait(); // Release the lock so other threads can acquire it
          System.out.println(Thread.currentThread().getName() + " wakes up");
        } else {
          System.out.println(Thread.currentThread().getName() + " calling the notify method");
        }
        notify(); // Notifying the random thread which is in waiting state to resume again
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println(Thread.currentThread().getName() + " terminates");
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...