操作系统中读者与写者问题

问题描述

  1. 计算机中的数据常被若干个并发程序所共享,某些进程可能只希望“读数据”,读完过后,该数据仍然存在且并未发生任何修改,该进程即为“读进程”。同样有一些进程访问数据时,需要对所访问的数据进行修改,原数据将被修改数据替代,不复存在。该类进程即为“写进程”。
  2. 多个读进程可以并发的交替访问共享数据资源,但写进程与读进程(写进程)不能同时访问共享数据资源,这样可能导致数据的不一致。

问题分析

  1. 找出题目中所描述的各个进程,分析它们的互斥、同步关系。
  2. 根据进程的操作流程写出大致的P、V操作。
  3. 设置信号量。通过题目给出的已知的条件确定对应的同步信号量的初值(根据对应资源的多少),互斥信号量的初始值一般设为mutex=1。
  4. 具体分析:
    两类进程:读进程、写进程。
    互斥关系:写进程与读进程、写进程与写进程。
    写进程与任何进程都互斥,设置互斥信号量为wmutex,在写者访问共享资源的前后分别加上P、V操作。因为写者与读者的互斥,在共享资源时,也会执行P(wmutex)操作,这样就会导致后续的读者一直处于阻塞状态。如何防止该类事件的发生呐?我们可以让第一个访问资源的读进程占用该资源,最后一个访问的读进程释放该资源,通过变量count来记录访问共享数据读进程的个数。这样就可以解决多个读进程可以共享同一数据资源了。

问题实现

读者-写者问题可分为3种情况实现:

  1. 读者优先
  2. 写者优先
  3. 公平竞争
    读者优先
    信号量的设置
    读、写进程操作
    写者优先
    信号量设置
    读、写进程操作
    公平竞争
    信号量设置
    读、写进程操作

总结

读者-写者问题为我们解决复杂的互斥问题提供了参考思路。它对共享资源的访问类型分成两类:读操作和写操作。对于进行读操作的进程,其对共享资源的访问时共享式的;对于进行写操作的进程,其对共享资源的访问是互斥的,且读、写操作也需互斥,否则将导致数据的不一致。

  • 3
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 读者写者问题是指多个线程同时访问共享资源的情况下可能引发的竞态条件问题,其包括读者进程和写者进程。 在C语言,可以使用互斥量和条件变量来实现读者写者问题的解决方案。 下面是一个简单的读者写者问题的C代码实现: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define READERS_COUNT 5 // 读者数量 #define WRITERS_COUNT 3 // 写者数量 pthread_mutex_t resource_mutex; // 互斥量,用于对共享资源的互斥访问 pthread_mutex_t read_mutex; // 互斥量,用于对读者计数器的互斥访问 pthread_mutex_t write_mutex; // 互斥量,用于对写者计数器的互斥访问 pthread_cond_t read_cond; // 条件变量,用于读者等待 pthread_cond_t write_cond; // 条件变量,用于写者等待 int readers_count = 0; // 读者计数器 int writer_count = 0; // 写者计数器 void *reader(void *arg) { int reader_id = *(int*) arg; while(1) { // 读者等待 pthread_mutex_lock(&resource_mutex); pthread_mutex_lock(&read_mutex); while(writer_count > 0) { pthread_cond_wait(&read_cond, &read_mutex); } readers_count++; pthread_mutex_unlock(&read_mutex); pthread_mutex_unlock(&resource_mutex); // 读取共享资源 printf("Reader %d is reading\n", reader_id); // 读者退出 pthread_mutex_lock(&read_mutex); readers_count--; if(readers_count == 0) { pthread_cond_signal(&write_cond); } pthread_mutex_unlock(&read_mutex); // 等待一段时间后再进行下一轮读取 sleep(rand() % 5); } } void *writer(void *arg) { int writer_id = *(int*) arg; while(1) { // 写者等待 pthread_mutex_lock(&write_mutex); writer_count++; while(readers_count > 0) { pthread_cond_wait(&write_cond, &write_mutex); } pthread_mutex_unlock(&write_mutex); // 写入共享资源 printf("Writer %d is writing\n", writer_id); // 写者退出 pthread_mutex_lock(&write_mutex); writer_count--; pthread_cond_signal(&read_cond); pthread_cond_signal(&write_cond); pthread_mutex_unlock(&write_mutex); // 等待一段时间后再进行下一轮写入 sleep(rand() % 5); } } int main() { pthread_t readers[READERS_COUNT]; pthread_t writers[WRITERS_COUNT]; int reader_ids[READERS_COUNT]; int writer_ids[WRITERS_COUNT]; int i; // 初始化互斥量和条件变量 pthread_mutex_init(&resource_mutex, NULL); pthread_mutex_init(&read_mutex, NULL); pthread_mutex_init(&write_mutex, NULL); pthread_cond_init(&read_cond, NULL); pthread_cond_init(&write_cond, NULL); // 创建读者线程 for(i = 0; i < READERS_COUNT; i++) { reader_ids[i] = i; pthread_create(&readers[i], NULL, reader, (void*)&reader_ids[i]); } // 创建写者线程 for(i = 0; i < WRITERS_COUNT; i++) { writer_ids[i] = i; pthread_create(&writers[i], NULL, writer, (void*)&writer_ids[i]); } // 等待所有读者写者线程结束 for(i = 0; i < READERS_COUNT; i++) { pthread_join(readers[i], NULL); } for(i = 0; i < WRITERS_COUNT; i++) { pthread_join(writers[i], NULL); } // 销毁互斥量和条件变量 pthread_mutex_destroy(&resource_mutex); pthread_mutex_destroy(&read_mutex); pthread_mutex_destroy(&write_mutex); pthread_cond_destroy(&read_cond); pthread_cond_destroy(&write_cond); return 0; } ``` 以上的代码实现了读者写者问题的解决方案,其使用互斥量和条件变量来保证资源的互斥访问和线程的同步。读者写者通过互斥量和条件变量的配合,实现了对共享资源的有序访问。读者优先,即当有写者等待时,读者必须等待;而当没有写者等待时,读者可以直接访问资源。写者在没有读者访问或等待时,直接访问资源。通过通过互斥量和条件变量的配合,读者写者问题得到了有效的解决。 ### 回答2: 读者写者问题是一个典型的并发问题,它涉及到多个并发执行的读进程和写进程对共享资源的访问和修改。在操作系统,可以使用信号量来实现读者写者问题读者进程可以并发地访问共享资源,而写者进程必须在没有读者进程和其他写者进程访问时,独占地访问和修改共享资源。 下面是一个简单的C代码实现: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> sem_t mutex; // 用于控制对资源的访问 sem_t wrt; // 用于控制写进程的访问 int reader_count = 0; // 记录当前读者的数量 void *reader(void *arg) { int id = (int)arg; sem_wait(&mutex); // 互斥访问reader_count reader_count++; if (reader_count == 1) { sem_wait(&wrt); // 阻塞写进程 } sem_post(&mutex); // 执行读操作 printf("Reader %d is reading.\n", id); sem_wait(&mutex); // 互斥访问reader_count reader_count--; if (reader_count == 0) { sem_post(&wrt); // 释放写进程 } sem_post(&mutex); pthread_exit(NULL); } void *writer(void *arg) { int id = (int)arg; sem_wait(&wrt); // 阻塞读进程和其他写进程 // 执行写操作 printf("Writer %d is writing.\n", id); sem_post(&wrt); // 释放读进程和其他写进程 pthread_exit(NULL); } int main() { int num_readers = 3; // 读者进程数量 int num_writers = 2; // 写者进程数量 sem_init(&mutex, 0, 1); sem_init(&wrt, 0, 1); pthread_t readers[num_readers]; pthread_t writers[num_writers]; // 创建读者进程 for (int i = 0; i < num_readers; i++) { pthread_create(&readers[i], NULL, reader, (void *)i); } // 创建写者进程 for (int i = 0; i < num_writers; i++) { pthread_create(&writers[i], NULL, writer, (void *)i); } // 等待所有读者进程结束 for (int i = 0; i < num_readers; i++) { pthread_join(readers[i], NULL); } // 等待所有写者进程结束 for (int i = 0; i < num_writers; i++) { pthread_join(writers[i], NULL); } sem_destroy(&mutex); sem_destroy(&wrt); return 0; } ``` 在上述代码,通过使用两个信号量mutex和wrt来实现对资源的互斥访问。其mutex用于互斥访问reader_count,wrt用于控制写进程的访问。 在读者进程,首先使用sem_wait(&mutex)来对reader_count进行互斥访问,然后判断reader_count的值。如果reader_count为1(表示当前没有其他读者进程访问资源),则使用sem_wait(&wrt)来阻塞写进程。接着执行读操作,然后再次使用sem_wait(&mutex)来互斥访问reader_count,减小reader_count的值,并判断reader_count是否为0(表示当前没有其他读者进程访问资源),如果是,则使用sem_post(&wrt)来释放写进程。 在写者进程,使用sem_wait(&wrt)来阻塞读进程和其他写进程,执行写操作,然后使用sem_post(&wrt)来释放读进程和其他写进程。 在main函数,通过创建和等待所有的读者写者线程来模拟读者写者的并发访问。 这样,就可以实现读者写者问题的C代码实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值