Concurrent programming based on semaphore mechanism

Operating system course design

1. Experimental purpose

(1) This paper reviews the concepts of process and thread in operating system, and designs concurrent programs for the classical problems of synchronization, mutual exclusion, deadlock and starvation.
(2) Understand mutex objects, use mutex and synchronization operations to write concurrent programs for reader writer problems, and deepen the understanding of P (i.e. semWait) and V (i.e. semSignal) primitives and P and V primitives for inter process synchronization and mutex operations.
(3) Understand the information mechanism supported by Linux, and use the semaphore system call programming of IPC to realize the dining problem of philosophers.

2. Design task:

(1) Concurrent programming for reader writer problem
(2) The concurrent programming of philosophers' dining problem can be completed by choosing one of the above two tasks.

3. Background knowledge

(1) For Windows API functions related to concurrency control, please refer to experiment 5.
(2) UINX/Linux system refers to semaphores, message queues and shared resources as interprocess communication resources (IPC resources). IPC resources provided to users are implemented through a set of system calls. In task 2, semaphore system calls such as semget(), semop(), and semctl() provided in IPC will be used. For their brief introduction, please query the background knowledge of Experiment 4. Please further query the relevant information on how to use them.

4. Experiment contents and requirements

(1) Concurrent programming for reader writer problem
According to the actual Windows API functions corresponding to the familiar P and V primitives in Experiment 5, and referring to the algorithm principle of reader writer problem in the textbook, try to use Windows API functions to realize the first type of reader writer problem (reader first).

5. Description

emmmmm, because it's hard to change the code of this problem if you look at other big guys' blogs, so I told the teacher that I want to write first, The teacher table agrees (2333333), so my code is writer first. Generally speaking, writer first is similar to reader first, mainly to understand how semaphores control synchronization between processes and mutual exclusion within processes. In fact, these are not very difficult. Come on, later.
6. Code

#include<windows.h>
#include <iostream>
#include<stdio.h>

#define MAX_READER_NUM 512
#define READER_NUM 2
#define WRITER_NUM 3
#define MOD 100

using namespace std;

int readcount=0;
int writecount=0;
HANDLE a;//It says the first mutex of priority readers
HANDLE b;//The second mutex of the priority reader is written, which is also the semaphore that the writer blocks the reader
HANDLE c;//It says the third mutex for priority readers
HANDLE y;//This can be understood by referring to the pseudo code in the book
HANDLE middle;//A semaphore that implements mutual exclusion between readers and writers
HANDLE input;//This is to take the output as a critical resource, which helps to prevent two processes from outputting at the same time, resulting in the output that should be wrapped in one line. In addition, this is the output of readers, and the naming is not standardized
HANDLE output;//Like Input, this is the writer's output
DWORD WINAPI reader(LPVOID);//Call windows API function
DWORD WINAPI writer(LPVOID);
bool p_continue=true;
int test=0;
int process_write_num=0;//Count the execution times of each process
int process_read_num=0;

int main()
{
    a = CreateSemaphore(NULL,1,MAX_READER_NUM,NULL);
    b = CreateSemaphore(NULL,1,MAX_READER_NUM,NULL);
    c = CreateSemaphore(NULL,1,MAX_READER_NUM,NULL);
    input = CreateSemaphore(NULL,1,MAX_READER_NUM,NULL);
    output=CreateSemaphore(NULL,1,MAX_READER_NUM,NULL);
    middle = CreateSemaphore(NULL,1,MAX_READER_NUM,NULL);
    y=CreateSemaphore(NULL,1,MAX_READER_NUM,NULL);
    HANDLE hThreads[READER_NUM + WRITER_NUM];
    DWORD readerID[READER_NUM];
    DWORD writerID[WRITER_NUM];
    for(int i=0;i<WRITER_NUM;i++)
    {
        hThreads[i]=CreateThread(NULL,0,writer,NULL,0,&writerID[i]);//Create writer process
        if(hThreads[i]==NULL)
            return -1;
    }
    for(int i=0;i<READER_NUM;i++)
    {
        hThreads[i]=CreateThread(NULL,0,reader,NULL,0,&readerID[i]);//Create reader thread
        if(hThreads[i]==NULL)
            return -1;
    }
    while(p_continue)//End the program when you enter a space
    {
        if(getchar())
        {
            p_continue = false;
            printf("Number of reader processes in this process:%d\n",process_read_num);
            printf("Number of writer processes in this process:%d\n",process_write_num);
        }
    }
    return 0;
}

void READUNIT()
{
    WaitForSingleObject(input,INFINITE);//p operation
    process_read_num++;
    cout<<"A reader process starts reading:";
    cout<<test<<endl;
    ReleaseSemaphore(input,1,NULL);//v operation
}

void WRITEUNIT()
{
    process_write_num++;
    cout<<"A writer starts writing:";
    test=(test+1)%MOD;
    cout<<test<<endl;
    ReleaseSemaphore(output,1,NULL);
}

DWORD WINAPI writer(LPVOID lpPara)
{
    while(p_continue)
    {
        WaitForSingleObject(y,INFINITE);
        writecount++;
        if(writecount==1)
            WaitForSingleObject(b,INFINITE);
        ReleaseSemaphore(y,1,NULL);
        WaitForSingleObject(middle,INFINITE);
        WRITEUNIT();
        ReleaseSemaphore(middle,1,NULL);
        WaitForSingleObject(y,INFINITE);
        writecount--;
        if(writecount==0)
            ReleaseSemaphore(b,1,NULL);
        ReleaseSemaphore(y,1,NULL);
        Sleep(300);
    }
    return 0;
}

DWORD WINAPI reader(LPVOID lpParar)
{
    while(p_continue)
    {
        WaitForSingleObject(a,INFINITE);
        WaitForSingleObject(b,INFINITE);
        WaitForSingleObject(c,INFINITE);
        readcount++;
        if(readcount==1)
            WaitForSingleObject(middle,INFINITE);
        ReleaseSemaphore(a,1,NULL);
        ReleaseSemaphore(b,1,NULL);
        ReleaseSemaphore(c,1,NULL);
        READUNIT();
        WaitForSingleObject(c,INFINITE);
        readcount--;
        if(readcount==0)
            ReleaseSemaphore(middle,1,NULL);
        ReleaseSemaphore(c,1,NULL);
        Sleep(200);
    }
    return 0;
}

In general, emmmmm still looks too much at other people's code. It almost simulates the code written by others, 23333, but there are many course settings that can't be copied, However, you can update it on the basis of others (of course, it's not a simple change of output and variable names, 23333). Well, here you are. For some parts of the code that you can't understand, please refer to the following link. The comments of the following big man's article are very clear!!!!
Reference link: https://blog.csdn.net/RongLin02/article/details/118309933?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164027411316780269882632%2522%252C%2522scm%2522%253A%252220140713.130102334 …%2522%257D&request_ id=164027411316780269882632&biz_ id=0&utm_ medium=distribute. pc_ search_ result. none-task-blog-2alltop_ positive~default-1-118309933. pc_ search_ insert_ es_ download_ v2&utm_ term=%E5%9F%BA%E4%BA%8E%E4%BF%A1%E5%8F%B7%E9%87%8F%E6%9C%BA%E5%88%B6%E7%9A%84%E5%B9%B6%E5%8F%91%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%0A++++++++++++++++++++++++++&spm=1018.2226. three thousand and one point four one eight seven

Keywords: Operating System

Added by joquius on Sun, 26 Dec 2021 06:02:48 +0200