读写器prob在Java中使用信号量错误的线程名称,无法并发运行和显示并发性
虽然这看起来像是一个重复的问题,但在互联网上使用Java中的信号量并没有一个正确的读写器问题的工作实现。我发现的最接近的情况是给出了一个备选方案作为答案,但没有使用信号量 我是Java多线程新手,所以请耐心听我说。这是我的密码:读写器prob在Java中使用信号量错误的线程名称,无法并发运行和显示并发性,java,multithreading,concurrency,Java,Multithreading,Concurrency,虽然这看起来像是一个重复的问题,但在互联网上使用Java中的信号量并没有一个正确的读写器问题的工作实现。我发现的最接近的情况是给出了一个备选方案作为答案,但没有使用信号量 我是Java多线程新手,所以请耐心听我说。这是我的密码: import java.util.concurrent.Semaphore; class ReaderWritersProblem { static Semaphore readLock = new Semaphore(1); static Sema
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”。而且,所有这些似乎都不是同时执行的。如何仅使用信号量纠正读写器问题的实现?使用
ReentrantReadLock
etc可以简单地实现这一点,但却超出了问题的目的,问题的目的明确地说是使用信号量实现问题。谢谢
编辑:另外,如何显示多线程读取?我正在一个接一个地得到执行结果
编辑:更正代码:我已更正算法。我想回顾一下
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();
}
}
我假设您的问题与此代码为什么不并发执行有关。这是因为您必须调用方法t1.start(),而不是t1.run()(对于所有其他线程也是如此)。t1.run()将在主线程的上下文中而不是在新线程中运行run()方法 当您已经用二进制信号量保护代码时,我看不到同步方法的意义。两个线程将无法同时获取二进制信号量,只要线程不盲目释放信号量,代码就会安全。这就克服了拥有多个读卡器线程的所有问题
针对注释中的新问题进行了更新-如果希望多个读卡器线程访问同一节,则不应使用二进制信号量,而应使用值更大的信号量(最好等于读卡器线程数)。所有这些线程都可以获取信号量,并在完成时释放它们。另外,当许多读卡器线程处于活动状态时,必须特别注意不要使写卡器线程饥饿。这可以通过多种方式实现——只需谷歌为读者和作者解决问题,您将了解如何做到这一点。这解决了问题的一部分,谢谢。请参阅更新问题。如何获得显示并发线程读取的输出?好的,谢谢。我还希望输出类似“线程2正在读取,线程3正在读取,线程2已完成读取”等的内容,以显示多个线程可以同时读取。在这种情况下,我必须将
readLock
信号量的上限更改为>1正确吗?代码的其余部分也可以吗?我已经更新了答案。但我仍然不理解代码的某些部分,比如为什么要在读线程中获取writer锁。因此,我保留对您的代码的一般评论。如果您有时间,我想知道对代码的最佳更改是什么。另外,我是否应该对readCount
变量使用AtomicInteger
?写入程序锁是在读卡器线程中获取的,因为如果读卡器的数量大于1,则写入程序无法访问关键部分。我提到了维基百科上的伪代码: