[C/C++ solves the reader-writer problem]

1. Problem description

There are two sets of concurrent processes, readers and writers, sharing a file. When two or more reading processes (only read data, will not affect the data, and consumers will take the data away when they read the data, so Two consumers cannot read data together) There will be no side effects when accessing shared data at the same time, but if a writing process and other processes (reading process or writing process) access shared data at the same time, it may cause data inconsistency errors.
Therefore requires:

  1. Allow multiple readers to perform read operations on the file at the same time;
  2. Only one writer is allowed to write information to the file;
  3. Any writer does not allow other readers or writers to work until the write operation is complete;
  4. Before the writer executes the write operation, all existing readers and writers should exit.

2. Problem analysis

  • First, analyze the synchronization mutual exclusion relationship in the problem. Readers and writers are mutually exclusive, writers and writers are mutually exclusive, and readers and readers are not mutually exclusive.
  • Second, consider the case where read and write processes run concurrently. If readers and writers read or write data concurrently, we should prioritize the reader process, the writer process, or read-write fairness.
  • Finally, the semaphore is designed to control the mutual exclusion relationship and the priority execution strategy between readers and writers.

Three, three strategies to achieve

/*  本项目仅用于模拟解决读者-写者问题。
    1.包含若干读者线程和写者线程用于模拟读者进程和写者进程。
    2.包含一个单个资源临界缓冲区用于存放和读取数据。
    3.分别实现读者优先、写者优先以及读写公平三种策略。
*/

1. Reader first strategy

insert image description here
ReadHighPriority.cpp

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

#define NUM_READERS 3   //读者进程数量
#define NUM_WRITERS 2   //写者进程数量

static int data = 0;   //初始化临界缓存区为空
static int readers_count = 0;  //记录读者进程数量
static HANDLE mutex;   //用于实现读者进程对于readers_count变量的互斥访问
static HANDLE rw_semaphore;    //用于实现读者和写者互斥访问临界缓冲区

static DWORD WINAPI Reader(LPVOID lpParam) {
    
    
    int reader_id = *(int*)lpParam;

    while (1) {
    
    
        WaitForSingleObject(mutex, INFINITE);
        readers_count++;
        if (readers_count == 1) {
    
    
            WaitForSingleObject(rw_semaphore, INFINITE);
        }
        ReleaseMutex(mutex);

        printf("Reader %d is reading data: %d\n", reader_id, data);
        Sleep(1000);  // 模拟读取数据的耗时

        WaitForSingleObject(mutex, INFINITE);
        readers_count--;
        if (readers_count == 0) {
    
    
            ReleaseSemaphore(rw_semaphore, 1, NULL);
        }
        ReleaseMutex(mutex);

        Sleep(2000);  // 读者休息一段时间后再次读取数据
    }

    return 0;
}

DWORD WINAPI Writer(LPVOID lpParam) {
    
    
    int writer_id = *(int*)lpParam;

    while (1) {
    
    
        WaitForSingleObject(rw_semaphore, INFINITE);

        data++;  // 写入数据
        printf("Writer %d is writing data: %d\n", writer_id, data);
        Sleep(2000);  // 模拟写入数据的耗时

        ReleaseSemaphore(rw_semaphore, 1, NULL);

        Sleep(3000);  // 写者休息一段时间后再次写入数据
    }

    return 0;
}

int main() {
    
    
    // 创建互斥锁和读写信号量
    mutex = CreateMutex(NULL, FALSE, NULL);
    rw_semaphore = CreateSemaphore(NULL, 1, 1, NULL);

    // 创建读者线程
    HANDLE reader_threads[NUM_READERS];
    int reader_ids[NUM_READERS];
    for (int i = 0; i < NUM_READERS; i++) {
    
    
        reader_ids[i] = i + 1;
        reader_threads[i] = CreateThread(NULL, 0, Reader, &reader_ids[i], 0, NULL);
    }

    // 创建写者线程
    HANDLE writer_threads[NUM_WRITERS];
    int writer_ids[NUM_WRITERS];
    for (int i = 0; i < NUM_WRITERS; i++) {
    
    
        writer_ids[i] = i + 1;
        writer_threads[i] = CreateThread(NULL, 0, Writer, &writer_ids[i], 0, NULL);
    }

    // 等待所有读者线程和写者线程结束
    WaitForMultipleObjects(NUM_READERS, reader_threads, TRUE, INFINITE);
    WaitForMultipleObjects(NUM_WRITERS, writer_threads, TRUE, INFINITE);

    // 关闭句柄
    CloseHandle(mutex);
    CloseHandle(rw_semaphore);

    return 0;
}

2. Read and write fairness strategy

insert image description here

ReadrWriterEqualPriority.cpp

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

#define NUM_READERS 3   //读者进程数量
#define NUM_WRITERS 2   //写者进程数量

static int data = 0;   //初始化临界缓存区为空
static int readers_count = 0;  //记录读者进程数量
static HANDLE mutex;   //用于实现读者进程对于readers_count变量的互斥访问
static HANDLE rw_semaphore;    //用于实现读者和写者互斥访问临界缓冲区
static HANDLE w_priority;   //用于实现写优先

static DWORD WINAPI Reader(LPVOID lpParam) {
    
    
    int reader_id = *(int*)lpParam;

    while (1) {
    
    
        WaitForSingleObject(w_priority, INFINITE);
        WaitForSingleObject(mutex, INFINITE);
        readers_count++;
        if (readers_count == 1) {
    
    
            WaitForSingleObject(rw_semaphore, INFINITE);
        }
        ReleaseMutex(mutex);
        ReleaseSemaphore(w_priority, 1, NULL);

        printf("Reader %d is reading data: %d\n", reader_id, data);
        Sleep(1000);  // 模拟读取数据的耗时

        WaitForSingleObject(mutex, INFINITE);
        readers_count--;
        if (readers_count == 0) {
    
    
            ReleaseSemaphore(rw_semaphore, 1, NULL);
        }
        ReleaseMutex(mutex);

        Sleep(2000);  // 读者休息一段时间后再次读取数据
    }

    return 0;
}

DWORD WINAPI Writer(LPVOID lpParam) {
    
    
    int writer_id = *(int*)lpParam;

    while (1) {
    
    
        WaitForSingleObject(w_priority, INFINITE);
        WaitForSingleObject(rw_semaphore, INFINITE);

        data++;  // 写入数据
        printf("Writer %d is writing data: %d\n", writer_id, data);
        Sleep(2000);  // 模拟写入数据的耗时

        ReleaseSemaphore(rw_semaphore, 1, NULL);
        ReleaseSemaphore(w_priority, 1, NULL);

        Sleep(3000);  // 写者休息一段时间后再次写入数据
    }

    return 0;
}

int main() {
    
    
    // 创建互斥锁和读写信号量
    mutex = CreateMutex(NULL, FALSE, NULL);
    rw_semaphore = CreateSemaphore(NULL, 1, 1, NULL);
    w_priority = CreateSemaphore(NULL,1,1,NULL);

    // 创建读者线程
    HANDLE reader_threads[NUM_READERS];
    int reader_ids[NUM_READERS];
    for (int i = 0; i < NUM_READERS; i++) {
    
    
        reader_ids[i] = i + 1;
        reader_threads[i] = CreateThread(NULL, 0, Reader, &reader_ids[i], 0, NULL);
    }

    // 创建写者线程
    HANDLE writer_threads[NUM_WRITERS];
    int writer_ids[NUM_WRITERS];
    for (int i = 0; i < NUM_WRITERS; i++) {
    
    
        writer_ids[i] = i + 1;
        writer_threads[i] = CreateThread(NULL, 0, Writer, &writer_ids[i], 0, NULL);
    }

    // 等待所有读者线程和写者线程结束
    WaitForMultipleObjects(NUM_READERS, reader_threads, TRUE, INFINITE);
    WaitForMultipleObjects(NUM_WRITERS, writer_threads, TRUE, INFINITE);

    // 关闭句柄
    CloseHandle(mutex);
    CloseHandle(rw_semaphore);
    CloseHandle(w_priority);
    return 0;
}

3. Writer priority strategy (subsequent updates)

Guess you like

Origin blog.csdn.net/wddkxg/article/details/131427742