为什么要进行并发控制
在并发程序中,多个进程或者线程的运行,本来是可以毫无关系的,也就是完全的异步执行,但是现实中往往异步执行不能满足需求
- 假如只有一个苹果,A和B都要执行吃苹果的程序,如果只是异步执行的话,他们都会认为自己吃完了苹果,但是无法确定到底谁吃到了苹果
引出的问题就是并发执行的程序要想对共同的资源进行访问,需要实现同步,才可以保证对于共同资源的有序使用,避免出现问题。
P/V信号量编程
- 临界资源:并发程序需要访问的相同的资源
- P操作是指,检测临界区域能否使用,等待资源
- V操作是指,释放临界资源,通知等待的进程
实现读者写者的并发控制(读者优先)
-
问题分析
对于同样的资源,读的时候不能写,写的时候不能读,也就是读写互斥,用信号量可以完美实现 -
实现思路
- 读者线程
- 读者可以并发的读临界资源,因此,可以不对读操作加互斥量
- 读者优先的特性应该在读者线程中体现出来,即只有读者全部读完之后,才会释放临界资源
- 为了保证所有的读者都读完再进行临界资源的释放,需要统计读者的数量,每个读线程为readCount加1,读完之后再减1
关键
对于readCount加1减1的操作,如果不进行同步,多个读线程共同操作,会出现同步问题,因此,需要对readCount的操作加互斥量,保证只有一个读者对这一数字进行改变
- 写者线程
写者只能单独写临界资源,因此,需要对写操作加互斥量
- 读者线程
-
待解决疑问
如果一个写线程在使用资源,一个读线程和一个写线程都在等待资源,如何保证写线程写完释放资源之后,可以将资源分配给读线程,保证读者优先 -
代码分析
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
#include <fstream>
#include <iostream>
using namespace std;
#define sleep(n) Sleep(n*1000)
struct ThreadInfo
{
int tid; //线程ID
char role; //扮演角色 R or W
double delay; //线程延迟
double persist; //线程读写操作持续时间
};
int ReadCount = 0; //读者数量
HANDLE Rmutex; //信号量
CRITICAL_SECTION RW_mutex; //临界区
void ReaderThread(void * p)
{
//创建线程会传入相关参数
//DWORD全称Double Word,每个word为2个字节的长度,DWORD 双字即为4个字节,每个字节是8位,共32位。
DWORD m_delay = ((ThreadInfo *)(p))->delay;
DWORD m_persist = (