我是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();
}
}
}