操作系统课后作业

文章详细介绍了如何使用条件变量和互斥量解决生产者消费者问题,以及实现读者写者问题的两种变体:写者优先和公平竞争。在生产者消费者问题中,解释了为何需要加锁和使用while循环的原因。在读者写者问题中,展示了如何保证写者线程的优先级以及允许多个读者同时访问资源。

这次作业不知到第几章,但是,who cares? 知识未学到,作业先行,你懂得,还是我们万能的chatGPT。

目录

第一题

题目要求

解答

第二题

题目要求

解答

写者优先

题目要求

解答

代码实现

公平竞争

题目要求

解答

代码实现


第一题

题目要求

使用Condition Variables编写生产者消费者问题(假设缓冲区大小为10,系统中有五个生产者,是个消费者)。并回答以下问题:

1.在生产者和消费者线程中修改条件时为什么要加mutex?

2.消费者线程中判断条件为什么要放在while而不是if中?

解答

下面是使用C语言编写生产者消费者问题,并回答给出的问题:

 #include <stdio.h>
 #include <stdlib.h>
 #include <pthread.h>
 ​
 #define BUFFER_SIZE 10
 #define NUM_PRODUCERS 5
 #define NUM_CONSUMERS 1
 #define NUM_ITEMS 20
 ​
 int buffer[BUFFER_SIZE];
 int count = 0;
 int in = 0;
 int out = 0;
 ​
 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 pthread_cond_t buffer_empty = PTHREAD_COND_INITIALIZER;
 pthread_cond_t buffer_full = PTHREAD_COND_INITIALIZER;
 ​
 void *producer(void *arg) {
     int id = *(int *)arg;
 ​
     for (int i = 0; i < NUM_ITEMS; ++i) {
         pthread_mutex_lock(&mutex);
         while (count == BUFFER_SIZE) {
             pthread_cond_wait(&buffer_full, &mutex);
         }
 ​
         buffer[in] = id;
         in = (in + 1) % BUFFER_SIZE;
         count++;
 ​
         pthread_cond_signal(&buffer_empty);
         pthread_mutex_unlock(&mutex);
     }
 ​
     pthread_exit(NULL);
 }
 ​
 void *consumer(void *arg) {
     for (int i = 0; i < NUM_ITEMS * NUM_PRODUCERS / NUM_CONSUMERS; ++i) {
         pthread_mutex_lock(&mutex);
         while (count == 0) {
             pthread_cond_wait(&buffer_empty, &mutex);
         }
 ​
         int item = buffer[out];
         out = (out + 1) % BUFFER_SIZE;
         count--;
 ​
         pthread_cond_signal(&buffer_full);
         pthread_mutex_unlock(&mutex);
 ​
         printf("Consumed item: %d\n", item);
     }
 ​
     pthread_exit(NULL);
 }
 ​
 int main() {
     pthread_t producers[NUM_PRODUCERS];
     pthread_t consumers[NUM_CONSUMERS];
 ​
     int producer_ids[NUM_PRODUCERS];
     for (int i = 0; i < NUM_PRODUCERS; ++i) {
         producer_ids[i] = i + 1;
         pthread_create(&producers[i], NULL, producer, &producer_ids[i]);
     }
 ​
     for (int i = 0; i < NUM_CONSUMERS; ++i) {
         pthread_create(&consumers[i], NULL, consumer, NULL);
     }
 ​
     for (int i = 0; i < NUM_PRODUCERS; ++i) {
         pthread_join(producers[i], NULL);
     }
 ​
     for (int i = 0; i < NUM_CONSUMERS; ++i) {
         pthread_join(consumers[i], NULL);
     }
 ​
     return 0;
 }
  1. 在生产者和消费者线程中修改条件时需要加锁(使用互斥量 mutex),是为了保证同一时间只有一个线程能够访问和修改条件。这是为了避免多个线程同时修改条件而导致竞态条件(race condition)的发生,确保线程安全。

  2. 消费者线程中判断条件为了放在 while 而不是 if 中,是因为在多线程环境下,当消费者线程被唤醒后,需要重新检查条件是否满足。如果使用 if 条件判断,那么当多个消费者线程被唤醒时,只有一个线程能够进入临界区,其他线程会继续执行,可能会导致条件不满足,从而导致错误。通过使用 while 循环判断条件,消费者线程在被唤醒后会重新检查条件是否满足,如果条件不满足,线程会再次进入等待状态,直到条件满足才会继续执行,确保正确性。

第二题

题目要求

4个线程,线程1循环打印A,线程2循环打印B,线程3循环打印C,线程4循环打印D,完成下面两个问题:

1.输出ABCDABCDABCD......

2.输出DCBADCBADCBA.....

解答

输出ABCDABCDABCD......

 #include <stdio.h>
 #include <pthread.h>
 ​
 #define NUM_THREADS 4
 ​
 pthread_mutex_t mutex;
 pthread_cond_t cond;
 int current_thread = 1;
 ​
 void *print_thread(void *arg) {
     int thread_id = *(int *)arg;
     char letter;
 ​
     switch (thread_id) {
         case 1:
             letter = 'A';
             break;
         case 2:
             letter = 'B';
             break;
         case 3:
             letter = 'C';
             break;
         case 4:
             letter = 'D';
             break;
     }
 ​
     while (1) {
         pthread_mutex_lock(&mutex);
 ​
         while (current_thread != thread_id) {
             pthread_cond_wait(&cond, &mutex);
         }
 ​
         printf("%c", letter);
         fflush(stdout);
 ​
         if (current_thread == NUM_THREADS) {
             current_thread = 1;
         } else {
             current_thread++;
         }
 ​
         pthread_cond_broadcast(&cond);
         pthread_mutex_unlock(&mutex);
     }
 ​
     pthread_exit(NULL);
 }
 ​
 int main() {
     pthread_t threads[NUM_THREADS];
     int thread_ids[NUM_THREADS] = {1, 2, 3, 4};
 ​
     pthread_mutex_init(&mutex, NULL);
     pthread_cond_init(&cond, NULL);
 ​
     for (int i = 0; i < NUM_THREADS; ++i) {
         pthread_create(&threads[i], NULL, print_thread, &thread_ids[i]);
     }
 ​
     for (int i = 0; i < NUM_THREADS; ++i) {
         pthread_join(threads[i], NULL);
     }
 ​
     pthread_mutex_destroy(&mutex);
     pthread_cond_destroy(&cond);
 ​
     return 0;
 }
 ​

输出DCBADCBADCBA.....

 #include <stdio.h>
 #include <pthread.h>
 ​
 #define NUM_THREADS 4
 ​
 pthread_mutex_t mutex;
 pthread_cond_t cond;
 int current_thread = 4;
 ​
 void *print_thread(void *arg) {
     int thread_id = *(int *)arg;
     char letter;
 ​
     switch (thread_id) {
         case 1:
             letter = 'D';
             break;
         case 2:
             letter = 'C';
             break;
         case 3:
             letter = 'B';
             break;
         case 4:
             letter = 'A';
             break;
     }
 ​
     while (1) {
         pthread_mutex_lock(&mutex);
 ​
         while (current_thread != thread_id) {
             pthread_cond_wait(&cond, &mutex);
         }
 ​
         printf("%c", letter);
         fflush(stdout);
 ​
         if (current_thread == 1) {
             current_thread = NUM_THREADS;
         } else {
             current_thread--;
         }
 ​
         pthread_cond_broadcast(&cond);
         pthread_mutex_unlock(&mutex);
     }
 ​
     pthread_exit(NULL);
 }
 ​
 int main() {
     pthread_t threads[NUM_THREADS];
     int thread_ids[NUM_THREADS] = {1, 2, 3, 4};
 ​
     pthread_mutex_init(&mutex, NULL);
     pthread_cond_init(&cond, NULL);
 ​
     for (int i = 0; i < NUM_THREADS; ++i) {
         pthread_create(&threads[i], NULL, print_thread, &thread_ids[i]);
     }
 ​
     for (int i = 0; i < NUM_THREADS; ++i) {
         pthread_join(threads[i], NULL);
     }
 ​
     pthread_mutex_destroy(&mutex);
     pthread_cond_destroy(&cond);
 ​
     return 0;
 }
 ​

以上代码中,我们使用了互斥量 mutex 和条件变量 cond 来控制线程的顺序打印。每个线程在进入临界区之前会先等待自己的轮次,通过条件变量的等待和唤醒机制,实现了线程之间的同步和顺序控制。

写者优先

题目要求

  1. 写者线程的优先级高于读者进程

  1. 当写者到来时,只有那些已经获得授权的读进程才被允许完成它们的操作,写者之后到来的读者将被推迟,直到写者完成

  1. 当没有写者进程时读者进程应该能够同时读取文件

解答

下面是一个示例程序,使用线程和互斥锁(mutex)实现了一个简单的读者-写者问题。在该示例中,写者线程的优先级被设置为高于读者线程。

在这个示例程序中,读者线程通过 reader() 函数表示,写者线程通过 writer() 函数表示。通过使用互斥锁 mutex 和条件变量 reader_condwriter_cond,实现了对读者和写者的同步控制。

请注意,由于线程优先级的设置是特定于操作系统和线程库的,这里的示例程序并没有直接设置线程的优先级。要设置线程的优先级,您需要参考特定操作系统和线程库的文档,并使用相应的函数进行设置。

在该程序中,当写者线程到来时,只有那些已经获得授权的读者线程才能完成它们的操作,而后到来的读者线程将被推迟,直到写者线程完成。当没有写者线程时,读者线程可以同时读取文件。

代码实现

 #include <stdio.h>
 #include <stdlib.h>
 #include <pthread.h>
 ​
 #define READERS_COUNT 5
 #define WRITERS_COUNT 2
 ​
 pthread_mutex_t mutex;
 pthread_cond_t writer_cond, reader_cond;
 int readers_count = 0;
 int writers_count = 0;
 int authorized_readers = 0;
 ​
 void* reader(void* arg) {
     int reader_id = *(int*)arg;
     
     pthread_mutex_lock(&mutex);
     while (writers_count > 0) {
         pthread_cond_wait(&reader_cond, &mutex);
     }
     readers_count++;
     pthread_mutex_unlock(&mutex);
     
     // 读取文件
     printf("Reader %d is reading the file.\n", reader_id);
     
     pthread_mutex_lock(&mutex);
     readers_count--;
     if (readers_count == 0) {
         pthread_cond_signal(&writer_cond);
     }
     pthread_mutex_unlock(&mutex);
     
     pthread_exit(NULL);
 }
 ​
 void* writer(void* arg) {
     int writer_id = *(int*)arg;
     
     pthread_mutex_lock(&mutex);
     writers_count++;
     while (readers_count > 0 || authorized_readers > 0) {
         pthread_cond_wait(&writer_cond, &mutex);
     }
     authorized_readers = readers_count;
     pthread_mutex_unlock(&mutex);
     
     // 写入文件
     printf("Writer %d is writing to the file.\n", writer_id);
     
     pthread_mutex_lock(&mutex);
     writers_count--;
     authorized_readers = 0;
     pthread_cond_broadcast(&reader_cond);
     pthread_cond_signal(&writer_cond);
     pthread_mutex_unlock(&mutex);
     
     pthread_exit(NULL);
 }
 ​
 int main() {
     pthread_t readers[READERS_COUNT];
     pthread_t writers[WRITERS_COUNT];
     int reader_ids[READERS_COUNT];
     int writer_ids[WRITERS_COUNT];
     
     pthread_mutex_init(&mutex, NULL);
     pthread_cond_init(&reader_cond, NULL);
     pthread_cond_init(&writer_cond, NULL);
     
     // 创建读者线程
     for (int i = 0; i < READERS_COUNT; i++) {
         reader_ids[i] = i + 1;
         pthread_create(&readers[i], NULL, reader, &reader_ids[i]);
     }
     
     // 创建写者线程
     for (int i = 0; i < WRITERS_COUNT; i++) {
         writer_ids[i] = i + 1;
         pthread_create(&writers[i], NULL, writer, &writer_ids[i]);
     }
     
     // 等待读者线程结束
     for (int i = 0; i < READERS_COUNT; i++) {
         pthread_join(readers[i], NULL);
     }
     
     // 等待写者线程结束
     for (int i = 0; i < WRITERS_COUNT; i++) {
         pthread_join(writers[i], NULL);
     }
     
     pthread_mutex_destroy(&mutex);
     pthread_cond_destroy(&reader_cond);
     pthread_cond_destroy(&writer_cond);
     
     return 0;
 }
 ​

公平竞争

题目要求

  1. 优先级相同

  1. 写者、读者互斥访问

  1. 只能有一个写者访问临界区

  1. 可以有多个读者同时访问临界资源

解答

以下是一个满足您描述的要求的读者-写者问题的示例程序。在该示例中,使用互斥锁(mutex)和条件变量(condition variable)来实现对共享资源的互斥访问和同步。

在这个示例程序中,读者线程通过 reader() 函数表示,写者线程通过 writer() 函数表示。通过使用互斥锁 mutex 和条件变量 reader_condwriter_cond,实现了对共享资源的互斥访问和同步。

在这种方案中,多个读者线程可以同时访问临界资源,但只允许一个写者线程访问临界资源。当有写者线程在临界区时,其他读者线程会等待写者线程完成。当没有写者线程时,读者线程可以同时访问临界资源。

请注意,示例程序中没有直接设置线程的优先级。如果需要设置线程的优先级,您需要参考特定操作系统和线程库的文档,并使用相应的函数进行设置。

代码实现

 #include <stdio.h>
 #include <stdlib.h>
 #include <pthread.h>
 ​
 pthread_mutex_t mutex;
 pthread_cond_t writer_cond, reader_cond;
 int readers_count = 0;
 int writers_count = 0;
 ​
 void* reader(void* arg) {
     int reader_id = *(int*)arg;
 ​
     pthread_mutex_lock(&mutex);
     while (writers_count > 0) {
         pthread_cond_wait(&reader_cond, &mutex);
     }
     readers_count++;
     pthread_mutex_unlock(&mutex);
 ​
     // 读取临界资源
     printf("Reader %d is reading the critical resource.\n", reader_id);
 ​
     pthread_mutex_lock(&mutex);
     readers_count--;
     if (readers_count == 0) {
         pthread_cond_signal(&writer_cond);
     }
     pthread_mutex_unlock(&mutex);
 ​
     pthread_exit(NULL);
 }
 ​
 void* writer(void* arg) {
     int writer_id = *(int*)arg;
 ​
     pthread_mutex_lock(&mutex);
     writers_count++;
     while (readers_count > 0 || writers_count > 1) {
         pthread_cond_wait(&writer_cond, &mutex);
     }
     pthread_mutex_unlock(&mutex);
 ​
     // 写入临界资源
     printf("Writer %d is writing to the critical resource.\n", writer_id);
 ​
     pthread_mutex_lock(&mutex);
     writers_count--;
     pthread_cond_broadcast(&reader_cond);
     pthread_cond_signal(&writer_cond);
     pthread_mutex_unlock(&mutex);
 ​
     pthread_exit(NULL);
 }
 ​
 int main() {
     pthread_t readers[5];
     pthread_t writers[2];
     int reader_ids[5];
     int writer_ids[2];
 ​
     pthread_mutex_init(&mutex, NULL);
     pthread_cond_init(&reader_cond, NULL);
     pthread_cond_init(&writer_cond, NULL);
 ​
     // 创建读者线程
     for (int i = 0; i < 5; i++) {
         reader_ids[i] = i + 1;
         pthread_create(&readers[i], NULL, reader, &reader_ids[i]);
     }
 ​
     // 创建写者线程
     for (int i = 0; i < 2; i++) {
         writer_ids[i] = i + 1;
         pthread_create(&writers[i], NULL, writer, &writer_ids[i]);
     }
 ​
     // 等待读者线程结束
     for (int i = 0; i < 5; i++) {
         pthread_join(readers[i], NULL);
     }
 ​
     // 等待写者线程结束
     for (int i = 0; i < 2; i++) {
         pthread_join(writers[i], NULL);
     }
 ​
     pthread_mutex_destroy(&mutex);
     pthread_cond_destroy(&reader_cond);
     pthread_cond_destroy(&writer_cond);
 ​
     return 0;
 }
 ​
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值