题目描述:
某数据库有一个写进程、多个读进程,它们之间读、写操作的互斥要求是:
写进程运行时,其他读、写进程不能对数据库进行操作。读进程之间不互斥,可以同时读数据库。
请用信号量及PV操作描述这一组进程的工作过程。
思路如下(简单模拟):
设置一个数据库互斥访问的信号量
设置一个全局的读者计数器,然后设置相应的计数器互斥访问信号量
设置一个全局的写者计数器,然后设置相应的计数器互斥访问信号量
设置一个写者等待的互斥信号量 设置公平调度
简单采用一个计数器表示写者修改的数据
代码如下(简单模拟):
package ConcurrentControl;
import java.util.concurrent.Semaphore;
/**
题目描述:
公平的读者写者模式
某数据库有一个写进程、多个读进程,它们之间读、写操作的互斥要求是:
写进程运行时,其他读、写进程不能对数据库进行操作。读进程之间不互斥,可以同时读数据库。
一旦有“写者”等待时,新到达的“读者”必须等待,直到该“写者”完成数据访问为止。
请用信号量及PV操作描述这一组进程的工作过程。
思路如下:
设置一个数据库的互斥访问信号量
设置一个数据库记录读者数量计数器的互斥信号访问量
设置一个数据库记录写者数量计数器的互斥信号访问量
设置一个写者准备就绪信号量设置初始值为1,以保证读者写者可以公平访问 设置公平调度
*/
public class Problem_06 {
public static void main(String argv[]){
new Thread(new Reader()).start();
new Thread(new Reader()).start();
new Thread(new Writer()).start();
new Thread(new Reader()).start();
new Thread(new Reader()).start();
}
private static class DB{
public static Semaphore dbMutex = new Semaphore(1);
public static int readerCnt = 0;
public static Semaphore readerCntMutex = new Semaphore(1);
public static int writerCnt = 0;
public static Semaphore writerCntMutex = new Semaphore(1, true);
public static Semaphore writerWaitingMutex = new Semaphore(1);
public static int dbData = 0;
}
private static class Reader implements Runnable{
@Override
public void run() {
for(int loop=0; loop<10; loop++){
// 检测是否有已经有写者准备了的
try {
DB.writerWaitingMutex.acquire();
DB.readerCntMutex.acquire();
DB.readerCnt++;
// 第一个读者获取db
if(DB.readerCnt==1){
DB.dbMutex.acquire();
System.out.printf("****************************************\n");
System.out.printf("first reader in\n");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
DB.readerCntMutex.release();
// 一旦更新完readCnt就需要释放写者准备这个信号量
DB.writerWaitingMutex.release();
}
System.out.printf("\treader -> %s\n", Thread.currentThread().getName());
System.out.printf("\tdb data: %d\n", DB.dbData);
// 检查是不是最后一个读者
try {
DB.readerCntMutex.acquire();
DB.readerCnt--;
if(DB.readerCnt==0) {
DB.dbMutex.release();
System.out.printf("last reader out\n");
System.out.printf("****************************************\n");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
DB.readerCntMutex.release();
}
}
}
}
private static class Writer implements Runnable{
@Override
public void run() {
for(int loop=0; loop<10; loop++){
// 先获取写着准备信号量
try {
DB.writerWaitingMutex.acquire();
DB.dbMutex.acquire();
System.out.printf("****************************************\n");
System.out.printf("\twriter -> %s\n", Thread.currentThread().getName());
System.out.printf("\told data: %d\n", DB.dbData);
System.out.printf("\tnew data: %d\n", ++DB.dbData);
System.out.printf("****************************************\n");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
DB.dbMutex.release();
DB.writerWaitingMutex.release();
}
}
}
}
}