虽然这看起来可能是一个重复的问题,但是在使用Java中的信号量时,在互联网上没有一个正确的实现Reader的问题。我发现的最接近的是this,它给出了一个替代方案作为答案,但没有使用信号量。
我对Java的多线程很陌生,所以请容忍我.这是我的代码:
import java.util.concurrent.Semaphore;
class ReaderWritersProblem {
static Semaphore readLock = new Semaphore(1);
static Semaphore writeLock = new Semaphore(1);
static int readCount = 0;
static class Read implements Runnable {
@Override
public synchronized void run() {
try {
readLock.acquire();
readCount++;
if (readCount == 1) {
writeLock.acquire();
}
System.out.println("Thread "+Thread.currentThread().getName() + " is READING");
Thread.sleep(1500);
System.out.println("Thread "+Thread.currentThread().getName() + " has FINISHED READING");
readLock.release();
readCount--;
if(readCount == 0) {
writeLock.release();
}
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
static class Write implements Runnable {
@Override
public synchronized void run() {
try {
writeLock.acquire();
System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING");
Thread.sleep(2500);
System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING");
writeLock.release();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
public static void main(String[] args) throws Exception {
Read read = new Read();
Write write = new Write();
Thread t1 = new Thread(read);
t1.setName("thread1");
Thread t2 = new Thread(read);
t2.setName("thread2");
Thread t3 = new Thread(write);
t3.setName("thread2");
Thread t4 = new Thread(read);
t4.setName("thread4");
t1.run();
t2.run();
t3.run();
t4.run();
}
}我正在创建4个线程,3个用于阅读,1个用于编写。然而,产出是这样的:
线程主正在读取 线程主已完成读取。 线程主正在读取 线程主已完成读取。 线程主正在写 线程main已经完成了编写。 线程主正在读取 线程主已完成读取。
返回的线程名为“main”。而且,所有这些似乎都没有同时执行。如何仅使用信号量来纠正Reader问题的实现?使用ReentrantReadLock等只会简单地做到这一点,但却超出了问题的目的,后者明确表示使用信号量实现问题。谢谢
编辑:此外,我如何显示多个线程读取?我要一个接一个地得到执行结果。
编辑:修正代码:,我已经修正了算法。希望能对此进行一些回顾。
import java.util.concurrent.Semaphore;
class ReaderWritersProblem {
static Semaphore readLock = new Semaphore(1);
static Semaphore writeLock = new Semaphore(1);
static int readCount = 0;
static class Read implements Runnable {
@Override
public void run() {
try {
//Acquire Section
readLock.acquire();
readCount++;
if (readCount == 1) {
writeLock.acquire();
}
readLock.release();
//Reading section
System.out.println("Thread "+Thread.currentThread().getName() + " is READING");
Thread.sleep(1500);
System.out.println("Thread "+Thread.currentThread().getName() + " has FINISHED READING");
//Releasing section
readLock.acquire();
readCount--;
if(readCount == 0) {
writeLock.release();
}
readLock.release();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
static class Write implements Runnable {
@Override
public void run() {
try {
writeLock.acquire();
System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING");
Thread.sleep(2500);
System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING");
writeLock.release();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
public static void main(String[] args) throws Exception {
Read read = new Read();
Write write = new Write();
Thread t1 = new Thread(read);
t1.setName("thread1");
Thread t2 = new Thread(read);
t2.setName("thread2");
Thread t3 = new Thread(write);
t3.setName("thread3");
Thread t4 = new Thread(read);
t4.setName("thread4");
t1.start();
t3.start();
t2.start();
t4.start();
}
}发布于 2016-05-01 17:11:33
我假设您的问题与为什么此代码不同时执行有关。这是因为您必须调用方法t1.start()而不是t1.run() (对于所有其他线程也是如此)。t1.run()将在主线程的上下文中而不是在新线程中运行run()方法。
当您已经使用二进制信号量保护代码时,我看不到同步方法的意义。两个线程将不能同时获得二进制信号量,而且只要线程不盲目地释放信号量,您的代码就会是安全的。这就挫败了拥有多个读取器线程的整个过程。
对注释中的新问题进行更新--如果希望多个读取器线程访问同一部分,则不应使用二进制信号量,而应使用值更大的信号量(最好等于读取器线程的数量)。所有这些线程都可以获得信号量,并在完成时释放它们。此外,当许多读者线程处于活动状态时,必须特别注意不要饿死写入线程。这可以通过很多方式来完成--仅仅是针对读者的谷歌--作家的问题,你会发现你是如何做到的。
https://stackoverflow.com/questions/36969429
复制相似问题