java - Java 信号量,acquire() 和 release()
问题描述
我是 java 的初学者,我正在尝试使用 Semaphore。我试图编写一个有作者和读者的代码,我只尝试使用acquire()和release():
1)如果一个作家正在写作,那么同时没有其他作家可以写作,也没有读者可以阅读。
2)多个阅读器可以同时阅读,但如果至少有一个活动阅读器,那么作者就不能写任何东西。
因此,总而言之,可以有
- 一个阅读器,没有作者
- 多个阅读器,没有作者
- 一个作者,没有阅读器
我尝试编写下面的代码,我知道它可能非常糟糕,但我真的很难理解这个概念并且代码不起作用,我不知道如何修复它。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class Main
{
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
{
private int reader = 0;
private Semaphore write = new Semaphore(1);
public void readLock()
{
if (write.availablePermits() == 1)
{
reader++;
}
}
public void writeLock()
{
if (write.availablePermits() == 1)
{
try
{
write.acquire();
}
catch(InterruptedException e)
{
e.printStackTrace();;
}
}
}
public void readUnLock()
{
if (reader > 0)
reader--;
}
public void writeUnLock()
{
if (write.availablePermits() == 0)
{
write.release();
}
}
}
class Writer implements Runnable
{
private ReadWriteLock RW_lock;
public Writer(ReadWriteLock rw) {
RW_lock = rw;
}
public void run() {
while (true){
RW_lock.writeLock();
RW_lock.writeUnLock();
}
}
}
class Reader implements Runnable
{
private ReadWriteLock RW_lock;
public Reader(ReadWriteLock rw) {
RW_lock = rw;
}
public void run() {
while (true){
RW_lock.readLock();
RW_lock.readUnLock();
}
}
}
解决方案
您可以使用信号量按照以下解决方案来解决读写器问题。它处理所有提到的条件并使用java.util.concurrent.Semaphore
包来实现信号量。
http://www2.hawaii.edu/~walbritt/ics240/synchronization/ReaderWriterSolution.java
您必须在读取器和写入器上定义锁。以下是所有读卡器锁的接口。
interface RWLock{
public abstract void acquireReadLock(int readerNum);
public abstract void acquireWriteLock(int writerNum);
public abstract void releaseReadLock(int readerNum);
public abstract void releaseWriteLock(int writerNum);
}
Database.java
包含所有读写函数的定义:
class Database implements RWLock{
private int readerCount; // the number of active readers
private Semaphore mutex; // controls access to readerCount
private Semaphore db; // controls access to the database
public Database() {
readerCount = 0;
mutex = new Semaphore(1);
db = new Semaphore(1);
}
public void acquireReadLock(int readerNum) {
try{
//mutual exclusion for readerCount
mutex.acquire();
}
catch (InterruptedException e) {}
++readerCount;
// if I am the first reader tell all others
// that the database is being read
if (readerCount == 1){
try{
db.acquire();
}
catch (InterruptedException e) {}
}
System.out.println("Reader " + readerNum + " is reading. Reader count = " + readerCount);
//mutual exclusion for readerCount
mutex.release();
}
public void releaseReadLock(int readerNum) {
try{
//mutual exclusion for readerCount
mutex.acquire();
}
catch (InterruptedException e) {}
--readerCount;
// if I am the last reader tell all others
// that the database is no longer being read
if (readerCount == 0){
db.release();
}
System.out.println("Reader " + readerNum + " is done reading. Reader count = " + readerCount);
//mutual exclusion for readerCount
mutex.release();
}
public void acquireWriteLock(int writerNum) {
try{
db.acquire();
}
catch (InterruptedException e) {}
System.out.println("Writer " + writerNum + " is writing.");
}
public void releaseWriteLock(int writerNum) {
System.out.println("Writer " + writerNum + " is done writing.");
db.release();
}
}
现在您将需要分别实现读取器和写入器。通过获取锁并遵循上述条件:
- 一个读者,没有作家
- 多个读者,没有作者
- 一个作家没有读者
class Reader implements Runnable
{
private RWLock database;
private int readerNum;
public Reader(int readerNum, RWLock database) {
this.readerNum = readerNum;
this.database = database;
}
public void run() {
while (true) {
SleepUtilities.nap();
System.out.println("reader " + readerNum + " wants to read.");
database.acquireReadLock(readerNum);
// you have access to read from the database
// let's read for awhile .....
SleepUtilities.nap();
database.releaseReadLock(readerNum);
}
}
;
}
class Writer implements Runnable
{
private RWLock database;
private int writerNum;
public Writer(int w, RWLock d) {
writerNum = w;
database = d;
}
public void run() {
while (true){
SleepUtilities.nap();
System.out.println("writer " + writerNum + " wants to write.");
database.acquireWriteLock(writerNum);
// you have access to write to the database
// write for awhile ...
SleepUtilities.nap();
database.releaseWriteLock(writerNum);
}
}
}
最后你需要一个运行类来测试解决方案
import java.util.concurrent.Semaphore;
public class ReaderWriterSolution{
public static final int NUM_OF_READERS = 3;
public static final int NUM_OF_WRITERS = 2;
public static void main(String args[]){
RWLock database = new Database();
Thread[] readerArray = new Thread[NUM_OF_READERS];
Thread[] writerArray = new Thread[NUM_OF_WRITERS];
for (int i = 0; i < NUM_OF_READERS; i++) {
readerArray[i] = new Thread(new Reader(i, database));
readerArray[i].start();
}
for (int i = 0; i < NUM_OF_WRITERS; i++) {
writerArray[i] = new Thread(new Writer(i, database));
writerArray[i].start();
}
}
}
所有的类都包含在解决方案中。希望能帮助到你!
推荐阅读
- groovy - Groovy 'with' 方法的意外行为 - 变量分配静默失败
- php - 使用 PHP 和 AJAX 将数据库中的值填充到表中
- java - 如何在jsonObject中的数组中获取某些元素
- c# - 使用 JToken 时保留的内存
- r - sparklyr spark_read_parquet 来自 s3 错误
- python - 当nodejs产生子进程时python找不到pip安装的库
- c# - 对象列表
在 RAM 上占用太多内存 - multithreading - 你如何在颤动的另一个线程上运行操作?
- django - How to provide autocomplete street addresses functionality in django?
- reactjs - 根据下拉菜单中的对象选择更新状态