Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
读写器prob在Java中使用信号量错误的线程名称,无法并发运行和显示并发性_Java_Multithreading_Concurrency - Fatal编程技术网

读写器prob在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

虽然这看起来像是一个重复的问题,但在互联网上使用Java中的信号量并没有一个正确的读写器问题的工作实现。我发现的最接近的情况是给出了一个备选方案作为答案,但没有使用信号量

我是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”。而且,所有这些似乎都不是同时执行的。如何仅使用信号量纠正读写器问题的实现?使用
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,则写入程序无法访问关键部分。我提到了维基百科上的伪代码: