这次作业不知到第几章,但是,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;
}
-
在生产者和消费者线程中修改条件时需要加锁(使用互斥量
mutex),是为了保证同一时间只有一个线程能够访问和修改条件。这是为了避免多个线程同时修改条件而导致竞态条件(race condition)的发生,确保线程安全。 -
消费者线程中判断条件为了放在
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 来控制线程的顺序打印。每个线程在进入临界区之前会先等待自己的轮次,通过条件变量的等待和唤醒机制,实现了线程之间的同步和顺序控制。
写者优先
题目要求
-
写者线程的优先级高于读者进程
-
当写者到来时,只有那些已经获得授权的读进程才被允许完成它们的操作,写者之后到来的读者将被推迟,直到写者完成
-
当没有写者进程时读者进程应该能够同时读取文件
解答
下面是一个示例程序,使用线程和互斥锁(mutex)实现了一个简单的读者-写者问题。在该示例中,写者线程的优先级被设置为高于读者线程。
在这个示例程序中,读者线程通过 reader() 函数表示,写者线程通过 writer() 函数表示。通过使用互斥锁 mutex 和条件变量 reader_cond、writer_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;
}
公平竞争
题目要求
-
优先级相同
-
写者、读者互斥访问
-
只能有一个写者访问临界区
-
可以有多个读者同时访问临界资源
解答
以下是一个满足您描述的要求的读者-写者问题的示例程序。在该示例中,使用互斥锁(mutex)和条件变量(condition variable)来实现对共享资源的互斥访问和同步。
在这个示例程序中,读者线程通过 reader() 函数表示,写者线程通过 writer() 函数表示。通过使用互斥锁 mutex 和条件变量 reader_cond、writer_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;
}
文章详细介绍了如何使用条件变量和互斥量解决生产者消费者问题,以及实现读者写者问题的两种变体:写者优先和公平竞争。在生产者消费者问题中,解释了为何需要加锁和使用while循环的原因。在读者写者问题中,展示了如何保证写者线程的优先级以及允许多个读者同时访问资源。
1062

被折叠的 条评论
为什么被折叠?



