Java:如何解决读写器问题?

Java:如何解决读写器问题?,java,multithreading,concurrency,parallel-processing,synchronization,Java,Multithreading,Concurrency,Parallel Processing,Synchronization,我想为读者和作者的问题实现一个解决方案。主要规则是,一次只能写一个作者,没有其他作者或读者可以写或读,但如果一个作者不写,多个读者可以读。在main类中,我尝试使用executorService.execute运行线程,但我想我遇到了一些问题。我对执行器服务知之甚少。程序永远不会结束,我想可能会有一些输出问题 我的代码如下: import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; im

我想为读者和作者的问题实现一个解决方案。主要规则是,一次只能写一个作者,没有其他作者或读者可以写或读,但如果一个作者不写,多个读者可以读。在main类中,我尝试使用
executorService.execute运行线程,但我想我遇到了一些问题。我对执行器服务知之甚少。程序永远不会结束,我想可能会有一些输出问题

我的代码如下:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;


public class ReaderWriter {
public static void main(String [] args) {
    ExecutorService executorService = Executors.newCachedThreadPool();
    ReadWriteLock RW = new ReadWriteLock();


    executorService.execute(new Writer(RW));
    executorService.execute(new Writer(RW));
    executorService.execute(new Writer(RW));
    executorService.execute(new Writer(RW));

    executorService.execute(new Reader(RW));
    executorService.execute(new Reader(RW));
    executorService.execute(new Reader(RW));
    executorService.execute(new Reader(RW));
 }
}


class ReadWriteLock{
    static Semaphore readLock = new Semaphore(1);
    static Semaphore writeLock = new Semaphore(1);
    volatile static int readCount = 0;

    public void readLock() throws InterruptedException {

        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();
    }
    public void writeLock() throws InterruptedException {
        writeLock.acquire();
        System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING");
        Thread.sleep(2500);
        writeLock.release();
        System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING");
    }
}




class Writer implements Runnable
{
    private ReadWriteLock RW_lock;


    public Writer(ReadWriteLock rw) {
        RW_lock = rw;
    }

    public void run() {
        while (true){
            try {
                RW_lock.writeLock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}



class Reader implements Runnable
{
    private ReadWriteLock RW_lock;


    public Reader(ReadWriteLock rw) {
        RW_lock = rw;
    }
    public void run() {
        while (true){
            try {
                RW_lock.readLock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


}
输出不正确,我认为对于这个问题:

Thread pool-1-thread-1 is WRITING
Thread pool-1-thread-2 is WRITING
Thread pool-1-thread-1 has finished WRITING
Thread pool-1-thread-2 has finished WRITING
Thread pool-1-thread-3 is WRITING
Thread pool-1-thread-3 has finished WRITING
Thread pool-1-thread-4 is WRITING
Thread pool-1-thread-4 has finished WRITING
Thread pool-1-thread-5 is READING
Thread pool-1-thread-8 is READING
Thread pool-1-thread-7 is READING
Thread pool-1-thread-6 is READING
Thread pool-1-thread-8 has FINISHED READING
Thread pool-1-thread-5 has FINISHED READING
Thread pool-1-thread-8 is READING
Thread pool-1-thread-5 is READING
Thread pool-1-thread-6 has FINISHED READING
Thread pool-1-thread-6 is READING
Thread pool-1-thread-7 has FINISHED READING
Thread pool-1-thread-7 is READING
Thread pool-1-thread-5 has FINISHED READING
Thread pool-1-thread-5 is READING
Thread pool-1-thread-8 has FINISHED READING
在该输出中,有两个写入程序同时写入

输出编辑:

Thread pool-1-thread-1 is WRITING
Thread pool-1-thread-1 has finished WRITING
Thread pool-1-thread-1 is WRITING
Thread pool-1-thread-1 has finished WRITING
Thread pool-1-thread-4 is WRITING
Thread pool-1-thread-4 has finished WRITING
Thread pool-1-thread-3 is WRITING
Thread pool-1-thread-3 has finished WRITING
Thread pool-1-thread-2 is WRITING
Thread pool-1-thread-2 has finished WRITING
Thread pool-1-thread-8 is READING
Thread pool-1-thread-7 is READING
Thread pool-1-thread-5 is READING
Thread pool-1-thread-6 is READING
Thread pool-1-thread-8 has FINISHED READING
Thread pool-1-thread-7 has FINISHED READING
Thread pool-1-thread-5 has FINISHED READING
Thread pool-1-thread-6 has FINISHED READING

您需要在主方法中调用ExecutorService的shutdown或ShutdownAndWaitTermination方法。

您需要在主方法中调用ExecutorService的shutdown或ShutdownAndWaitTermination方法

程序永远不会结束,我想可能会有一些输出问题

ReadWriteLock
类中添加一个标志,以向
线程发出停止工作的信号:

private final AtomicBoolean keep_working = new AtomicBoolean(true);
ReadWriteLock
类中添加一个方法来通知线程停止:

public void stopThreads(){
    keep_working.set(false);
}
并添加查询标志的方法:

相应地调整
编写器
读取器
运行
方法:

 public void run() {
        while (RW_lock.keepWorking()){
           ...
        }
    }
在主类上,添加对方法
ExecutorService.awaitTermination()
ReadWriteLock.stopThreads
ExecutorService.shutdown()的调用:

输出不正确,我认为对于这个问题: (...) 在该输出中,有两个写入程序同时写入

这是因为:

public void writeLock() throws InterruptedException {
    writeLock.acquire();
    System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING");
    Thread.sleep(2500);
    writeLock.release();
    System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING");
}
在打印“已完成写入”之前释放锁,因此,等待释放锁的线程在第一个线程有时间打印“已完成写入”之前进入并打印“正在写入”。因此,您需要将代码更改为:

   public void writeLock() throws InterruptedException {
        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();
    }
主要规则是,一次只能写一个作家,其他作家不能 作者或读者可以写或读,但如果作者不写, 多个阅读器可以阅读

实际上,您可以利用Java接口

读写锁维护一对关联锁,一个用于 只读操作和一个用于写入的操作。可以保持读取锁 由多个读卡器线程同时执行,只要没有 写入程序。写入锁是独占的。所有读写锁 实现必须保证内存同步效果 写锁操作的类型(如锁接口中指定的)也保持不变 关于关联的读锁。就是一根线 成功获取读取锁将看到在 写锁的以前版本

读写锁允许在内存中实现更高级别的并发 访问互斥锁允许之外的共享数据。 它利用了这样一个事实,即虽然一次只有一个线程(一个 编写器线程)可以修改共享数据,在许多情况下,可以修改任意数量的 线程可以同时读取数据(因此读线程)。在里面 理论上,通过使用 读写锁定将比使用 互斥锁。实际上,这种并发性的增加将 只有在多处理器上完全实现,并且 共享数据的访问模式是合适的

通过使用该接口,您可以将
readLock
writeLock
方法大大简化为以下内容:

   public void readLock() throws InterruptedException {
        shared_resource.readLock().lock();
        System.out.println("Thread "+Thread.currentThread().getName() + " is READING");
        Thread.sleep(1500);
        System.out.println("Thread "+Thread.currentThread().getName() + " has FINISHED READING");
        shared_resource.readLock().unlock();
    }
    public void writeLock() throws InterruptedException {
        shared_resource.writeLock().lock();
        System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING");
        Thread.sleep(2500);
        System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING");
        shared_resource.writeLock().unlock();
    }
要完成此操作,应添加一个统计写入和读取次数的变量。因此,如果没有写入任何内容,则读取线程应该等待,同时,写入线程应该写入一些内容,依此类推

程序永远不会结束,我想可能会有一些输出问题

ReadWriteLock
类中添加一个标志,以向
线程发出停止工作的信号:

private final AtomicBoolean keep_working = new AtomicBoolean(true);
ReadWriteLock
类中添加一个方法来通知线程停止:

public void stopThreads(){
    keep_working.set(false);
}
并添加查询标志的方法:

相应地调整
编写器
读取器
运行
方法:

 public void run() {
        while (RW_lock.keepWorking()){
           ...
        }
    }
在主类上,添加对方法
ExecutorService.awaitTermination()
ReadWriteLock.stopThreads
ExecutorService.shutdown()的调用:

输出不正确,我认为对于这个问题: (...) 在该输出中,有两个写入程序同时写入

这是因为:

public void writeLock() throws InterruptedException {
    writeLock.acquire();
    System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING");
    Thread.sleep(2500);
    writeLock.release();
    System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING");
}
在打印“已完成写入”之前释放锁,因此,等待释放锁的线程在第一个线程有时间打印“已完成写入”之前进入并打印“正在写入”。因此,您需要将代码更改为:

   public void writeLock() throws InterruptedException {
        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();
    }
主要规则是,一次只能写一个作家,其他作家不能 作者或读者可以写或读,但如果作者不写, 多个阅读器可以阅读

实际上,您可以利用Java接口

读写锁维护一对关联锁,一个用于 只读操作和一个用于写入的操作。可以保持读取锁 由多个读卡器线程同时执行,只要没有 写入程序。写入锁是独占的。所有读写锁 实现必须保证内存同步效果 写锁操作的类型(如锁接口中指定的)也保持不变 关于关联的读锁。就是一根线 成功获取读取锁将看到在 写锁的以前版本

读写锁允许在内存中实现更高级别的并发 访问互斥锁允许之外的共享数据。 它利用了这样一个事实,即虽然一次只有一个线程(一个 编写器线程)可以修改共享数据,在许多情况下,可以修改任意数量的 线程可以同时读取数据(因此读卡器t