读者写者问题读者优先 C语言实现代码

本博客代码摘自Mic_H,我小小地修改了一些。
本博客记录自己的学习,疑问和理解。欢迎大家交流和指教。
作者原博客链接
我的代码和运行结果:

#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <accctrl.h>
#include <time.h>
unsigned int readcount = 0;
bool p_ccontinue = true; //控制程序结束
HANDLE RSemaphore; //改变readcount值时互斥
HANDLE WSemaphore; //写互斥
DWORD WINAPI Writer(LPVOID); //写者线程
DWORD WINAPI Reader(LPVOID); //读者线程
int main()
{
    RSemaphore = CreateSemaphore(NULL,1,1,NULL);
    WSemaphore = CreateSemaphore(NULL,1,1,NULL);
    const unsigned short Writer_COUNT = 3;//写者数量
    const unsigned short Reader_COUNT = 8;//读者数量
    const unsigned short THREADS_COUNT = Writer_COUNT+Reader_COUNT;
    HANDLE hThreads[THREADS_COUNT]; //各线程的 handle
    DWORD writerID[Writer_COUNT]; //写者线程的标识符
    DWORD readerID[Reader_COUNT]; //读者线程的标识符
 
    srand(time(0));
    int writer_count = 0;
    int reader_count = 0;
    for(int i = 0; i < Writer_COUNT + Reader_COUNT; i++)
    {
        int ran = rand()%10;
        if((ran < 5) && (writer_count < Writer_COUNT))//Writer
        {
            hThreads[i]=CreateThread(NULL,0,Writer,NULL,0,&writerID[writer_count]);
            if (hThreads[i]==NULL) return -1;
            writer_count++;
        }
        else if((ran >= 5) && (reader_count < Reader_COUNT))//Reader
        {
            hThreads[i]=CreateThread(NULL,0,Reader,NULL,0,&readerID[reader_count]);
            if (hThreads[i]==NULL) return -1;
            reader_count++;
        }
        Sleep(500);//等待500ms
    }
    while(p_ccontinue)
    {
        if(getchar())  //按回车后终止程序运行
        {
            p_ccontinue = false;
        }
    }
    return 0;
}
//写者
DWORD WINAPI Writer(LPVOID lpPara)
{
    while(p_ccontinue)
    {
        printf("\n%d is waiting to write...\n",GetCurrentThreadId());
        WaitForSingleObject(WSemaphore,INFINITE);//P(w)在读或在写时,写者阻塞
        printf("\n**  writer %d got the control\n",GetCurrentThreadId());
        //write...
        printf("\n%d is writing...\n",GetCurrentThreadId());
        Sleep(1500);
        printf("\n--- %d have finished the writing\n",GetCurrentThreadId());
        ReleaseSemaphore(WSemaphore,1,NULL);//V(w)写完,唤醒阻塞的读者或写者
        return 0;//结束此线程
    }
    return 0;
}
//读者
DWORD WINAPI Reader(LPVOID lpPara)
{
    while(p_ccontinue)
    {
        printf("\n%d is waiting to read...\n",GetCurrentThreadId());
        WaitForSingleObject(RSemaphore,INFINITE);//P(x)临界区互斥,所有读者修改readcount
        readcount++;
        if(readcount == 1)//第一个读,要等已经在写的写者写完才可以开始读
            WaitForSingleObject(WSemaphore,INFINITE);//P(w)有写时,读者阻塞
        //同时读,故要在Read()之前V(x)
        ReleaseSemaphore(RSemaphore,1,NULL);//V(x)
        //read...
        printf("\n%d is reading...\n",GetCurrentThreadId());
        Sleep(1500);
        printf("\n--- %d have finished the reading\n",GetCurrentThreadId());
        WaitForSingleObject(RSemaphore,INFINITE);//P(x)
        readcount--;
        if(readcount== 0)
        {
            printf("\n----- All Readers done\n");
            ReleaseSemaphore(WSemaphore,1,NULL);//V(w)都不读,唤醒阻塞的写者
        }
        ReleaseSemaphore(RSemaphore,1,NULL);//V(x)
        return 0;//结束此线程
    }
    return 0;
}
 
13656 is waiting to write...

**  writer 13656 got the control

13656 is writing...

33596 is waiting to read...

7620 is waiting to read...

--- 13656 have finished the writing

33596 is reading...

33596 is reading...

7620 is reading...

29964 is waiting to read...

29964 is reading...

31876 is waiting to write...

34616 is waiting to read...

34616 is reading...

--- 33596 have finished the reading

--- 33596 have finished the reading

--- 29964 have finished the reading

--- 33596 have finished the reading

--- 29964 have finished the reading
--- 7620 have finished the reading

32608 is waiting to read...

32608 is reading...

7800 is waiting to write...

--- 34616 have finished the reading

--- 32608 have finished the reading

----- All Readers done

**  writer 31876 got the control

31876 is writing...

--- 31876 have finished the writing

**  writer 7800 got the control

7800 is writing...

--- 7800 have finished the writing

以下是我自己实验的一些薄浅的理解和疑问(本人小白,写错了不要喷,欢迎大家指教)。
理解:1.通过srand获得随机数种子,ran获得随机数,经if语句的两个条件,决定创建是写线程还是读线程。但是这个for循环i是小于3+8的,如果write_count为3,即写线程创建完成了,但是此后有一个或者几个ran<5,既不会创建写线程,也不会创建读线程。所以不会创建8个读线程,大概率会小于8个读线程。(运行20次左右就出现一次)
2.写线程中的ReleaseSemaphore(WSemaphore,1,NULL)唤醒的是阻塞的读者或写者。我修改之后的程序运行,如果xxxx is waiting to read 在 xxxx is waiting 之前,这个写线程是先被调度的,所以先输出xxxx is writing 后输出 xxxx is reading。注意:绝对读者优先此处唤醒的是阻塞的读者。
3.sleep(500)可以表示写、读线程进入的过程。sleep(1500)可以表示写线程写的过程,读线程读的过程。
疑问:
1.for循环中的Writer_COUNT + Reader_COUNT改成THREADS_COUNT(极少时候没改变这个也会出现),部分xxxx is reading就会输出两次,但是xxxx is waiting to read只出现一次。(如图的33596就是这样)这个疑问不知道是怎么回事。读线程和写线程函数部分,我加了一些单词或者换成中文,前几次运行结果均会出现乱码,格式错误等问题,多运行几次后,每4.5次就会出现一次乱码(估计可能是我vc6++是中文破译版的问题)。
因为是刚刚学习操作系统中各种问题的代码实现,就有很多系统函数不知道。所以我做了一些笔记(字难看,勿喷),
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43752257/article/details/106975909