我是Java中多线程的新手,遇到过以下情况:
问题:
线程1到n执行一个名为critical()的方法。在此之前,它们执行一个名为uncritical()的方法。它们的同步约束是一次只能有一个执行critical(),并且所有线程必须在调用critical()之前完成执行uncritical()。可以假设n存储在一个变量n中,该变量可从所有线程访问。为线程设计一个同步机制。所有线程必须执行相同的代码。线程可能多次调用critical(),您应该确保在所有其他线程完成对critical()的第k次调用之前,线程不能调用critical()a(k+1)次。
这里有一个想法(我可能完全错了):

public class CriticalMonitor{
    public static int N = 0;

    public CriticalMonitor(int )

    public void uncritical(int threadID){
        System.out.println(“Thread ” + threadID+“: Uncritical!”);
        N--;
        if(N== 0) notifyAll();
     }

    public synchronized void critical(int threadID){
       while(N!=0){
         try{
            wait();
          }catch(InterruptedException e){
            System.out.println(“Critical failed”);
          }
        }
        System.out.println(“Thread ” + threadID+“: Critical!”);

     }
 }

public static class CriticalThread extends Thread{
    private final CriticalMonitor monitor;
    private int threadId;

    public CriticalThread (CriticalMonitor m, int id){
       monitor = m;
       monitor.N++;
       threadId = id;
    }

    public void run(){
       monitor.uncritical(threadId);
       //random number of calls to critical()?
       int rand = (int)(Math.random()*5);
       while(rand>=0){
         monitor.critical(threadId);
         rand--;
        }
     }
 }

我无法理解的问题是,如何确保所有其他踏板在线程调用critical()之前(k+1)完成对critical()的第k次调用。

最佳答案

使用CyclicBarrier
您可以使用线程数创建CyclicBarrier
要在所有n之前实现calluncritical(),您可以
先让屏障critical()await之前。当所有n个线程执行critical()时,它们将一起触发屏障。
实现一个线程不能调用critical()a(k+1)time,直到
其他线程已经完成了对critical()的第kth调用,我认为您可以调整循环。即使他们不需要呼叫uncritical()
他们应该调用critical()。所以在每一轮中,每一根线都会让障碍物知道他们已经到达了临界点。最后一个到达后,所有的线程将一起进入下一轮。
在CriticalMonitor中,您不再需要await,只需
wait-notify方法上使用syncronize关键字来保护它一次只能由一个线程执行。
代码应该是这样的。

public class CriticalThread extends Thread {

    private final CriticalMonitor monitor;
    private int threadId;
    private CyclicBarrier barrier;

    public CriticalThread(CriticalMonitor m, int id, CyclicBarrier barrier) {
        monitor = m;
        monitor.N++;
        threadId = id;
        this.barrier = barrier;
    }

    public void run() {
        monitor.uncritical(threadId);
        //random number of calls to critical()?
        try {
            barrier.await();
            int rand = (int) (Math.random() * 5);
            int time = 0;
            int limit = 5;
            while (time < limit) {
                if (rand > 0) {
                    monitor.critical(threadId);
                    rand--;
                }
                barrier.await();
                time++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用原子整数
首先,您需要设置为critical()以保证内存可见性。在每个AtomicInteger中,需要递减n,而在循环中需要递增n。
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class CriticalMonitor {
    public static int SOURCE_N = 0;
    public static AtomicInteger N = new AtomicInteger(SOURCE_N);
    public static ReentrantLock lock = new ReentrantLock(true);
    public static Condition condition = lock.newCondition();


    public void uncritical(int threadID) {
        System.out.println("Thread " + threadID + ": Uncritical!");
        N.getAndDecrement();
        if (N.get() == 0) {
            lock.lock();
            try {
                condition.signalAll();
            } finally {
                lock.unlock();
            }

        }
    }

    public void critical(int threadID) {
        lock.lock();
        try {
            while (N.get() != 0) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    System.out.println("Critical failed");
                }
            }
            System.out.println("Thread " + threadID + ":Critical !");
            N.getAndDecrement();
        } finally {
            lock.unlock();
        }
    }
}

关键线程
while(rand >= 0){
        monitor.critical(threadId);
        rand--;
        N.getAndIncrement();
        if (N.get() == 0) {
            lock.lock();
            try {
                condition.signal();
            } finally {
                lock.unlock();
            }
        }
 }

07-28 12:58