首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >读取器作者在Java中使用信号量的prob错误线程名,无法并发运行并显示并发性。

读取器作者在Java中使用信号量的prob错误线程名,无法并发运行并显示并发性。
EN

Stack Overflow用户
提问于 2016-05-01 17:08:14
回答 1查看 4.6K关注 0票数 2

虽然这看起来可能是一个重复的问题,但是在使用Java中的信号量时,在互联网上没有一个正确的实现Reader的问题。我发现的最接近的是this,它给出了一个替代方案作为答案,但没有使用信号量。

我对Java的多线程很陌生,所以请容忍我.这是我的代码:

代码语言:javascript
复制
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等只会简单地做到这一点,但却超出了问题的目的,后者明确表示使用信号量实现问题。谢谢

编辑:此外,我如何显示多个线程读取?我要一个接一个地得到执行结果。

编辑:修正代码:,我已经修正了算法。希望能对此进行一些回顾。

代码语言:javascript
复制
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();
    }
}
EN

回答 1

Stack Overflow用户

发布于 2016-05-01 17:11:33

我假设您的问题与为什么此代码不同时执行有关。这是因为您必须调用方法t1.start()而不是t1.run() (对于所有其他线程也是如此)。t1.run()将在主线程的上下文中而不是在新线程中运行run()方法。

当您已经使用二进制信号量保护代码时,我看不到同步方法的意义。两个线程将不能同时获得二进制信号量,而且只要线程不盲目地释放信号量,您的代码就会是安全的。这就挫败了拥有多个读取器线程的整个过程。

对注释中的新问题进行更新--如果希望多个读取器线程访问同一部分,则不应使用二进制信号量,而应使用值更大的信号量(最好等于读取器线程的数量)。所有这些线程都可以获得信号量,并在完成时释放它们。此外,当许多读者线程处于活动状态时,必须特别注意不要饿死写入线程。这可以通过很多方式来完成--仅仅是针对读者的谷歌--作家的问题,你会发现你是如何做到的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36969429

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档