gpt4 book ai didi

java - 确保所有其他线程在线程调用 critical() (k+1) 之前完成了对 critical() 的第 k 次调用

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:23:41 25 4
gpt4 key购买 nike

我是 Java 多线程的新手,遇到过以下问题:

问题:线程 1 到 n 执行一个名为 critical() 的方法。在此之前,他们执行一个名为 uncritical() 的方法。它们的同步约束是一次只能执行一个critical(),所有线程必须在critical()之前完成执行uncritical()> 可以调用。您可以假设 n 存储在可从所有线程访问的变量 n 中。为线程设计一个同步机制。所有线程必须执行相同的代码。线程可能会多次调用 critical(),您应该确保线程不能调用 critical() (k+1) 次,直到所有其他线程都已完成对 critical()kth 调用。

这是一个想法(我可能完全错了):

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()kth 调用critical() (k+1) 次。

最佳答案

使用循环屏障

您可以创建一个 CyclicBarrier线程数n

  • 要在所有 critical() 之前调用 uncritical(),您可以让屏障在 critical() 之前 await。当所有 n 个线程都执行完 uncritical() 后,它们将一起跳闸。
  • 要实现一个线程不能调用 critical() 一次 (k+1) 直到所有其他线程已完成对 critical() 的第 k 次调用,我认为您可以调整循环。即使他们不需要调用 critical(),他们应该调用 await。所以在每一轮中,每个线程都会让屏障知道他们已经到达了那个点。最后一个到达后,所有线程将一起进入下一轮。
  • 并且在 CriticalMonitor 中,您不再需要 wait-notify,只需在 critical() 方法上使用 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();
}
}
}

使用原子整数

首先,您需要设置为AtomicInteger 以保证内存可见性。在每个 critical 中,您需要递减 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();
}
}
}

关于java - 确保所有其他线程在线程调用 critical() (k+1) 之前完成了对 critical() 的第 k 次调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48588568/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com