Linux练习_线程练习_读者写者问题
Posted Leslie X徐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux练习_线程练习_读者写者问题相关的知识,希望对你有一定的参考价值。
经典线程同步案例 读者写者问题
案例介绍
- 进程:
- 写者进程——负责写入数据
- 读者进程——读取数据
- 分析:
- 当写者进程还没写完数据之前,读者只能等待阻塞,当写者写完以后,通知读者可以进行读取数据。
- 当读者读完数据后,反过来去通知写者继续写入数据
-
框图
-
代码:
/*
* 读者写者问题
* 轮流写入读取100次,写一个读一个
*
* */
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//共享资源
typedef struct
{
int value;
//读者条件变量和互斥锁
pthread_cond_t rc;
pthread_mutex_t rm;
int r_wait; //判断读者线程条件
//写者条件变量和互斥锁
pthread_cond_t wc;
pthread_mutex_t wm;
int w_wait; //判断写者线程条件
}Storage,*pStorage;
/*写入函数*/
void set_data(pStorage s, int value)
{
s->value = value;
}
/*读取函数*/
int get_data(pStorage s)
{
return s->value;
}
/*写者线程执行的线程运行函数*/
void* set_th(void* arg)
{
pStorage s = (pStorage)arg;
int i=1;
//循环100次
for(;i<=10;i++){
//写入数据并打印信息
set_data(s, i+100);
printf("0x%lx(%-5d) write data: %d\\n", pthread_self(), i, i+100);
pthread_mutex_lock(&s->rm);
//判断读者线程是否准备好
while(!s->r_wait){
//循环,先解锁,让读者线程执行读取数据,再加锁判断条件是否满足
pthread_mutex_unlock(&s->rm);
sleep(1); //睡眠时,跳至读者线程s->r_wait = 1;前
pthread_mutex_lock(&s->rm);
}
//读者条件清0
s->r_wait = 0;
pthread_mutex_unlock(&s->rm);
//唤醒读取线程
pthread_cond_broadcast(&s->rc); //跳至读者线程pthread_cond_wait(&s->rc, &s->rm); 下面
/*写者线程等待阻塞
*等待读者读取完数据后通知唤醒它
*然后继续写入数据
*/
pthread_mutex_lock(&s->wm);
s->w_wait = 1;
pthread_cond_wait(&s->wc, &s->wm); //跳至判断s->w_wait循环体
pthread_mutex_unlock(&s->wm);
}
return (void*)0;
}
/*读者线程执行的线程运行函数*/
void* get_th(void* arg)
{
pStorage s = (pStorage)arg;
int i=1;
//循环100次
for(;i<=10;i++){
pthread_mutex_lock(&s->rm);
//读者条件置1, 让写者执行写入数据
s->r_wait = 1;
//进入等待队列,等待唤醒
pthread_cond_wait(&s->rc, &s->rm); //跳至写者线程判断s->r_wait循环体
//解锁wait中的lock
pthread_mutex_unlock(&s->rm);
//读取数据并输出
int value = get_data(s); //资源被锁住时函数可以读取到数据吗?
printf("0x%lx(%-5d) read data: %d\\n", pthread_self(), i, value);
pthread_mutex_lock(&s->wm);
//判断写者线程是否准备好
while(!s->w_wait){
pthread_mutex_unlock(&s->wm);
sleep(1); //跳至写者线程s->w_wait = 1;处
pthread_mutex_lock(&s->wm);
}
s->w_wait = 0;
pthread_mutex_unlock(&s->wm);
pthread_cond_broadcast(&s->wc); //跳至写者线程pthread_cond_wait(&s->wc, &s->wm);下面
}
return (void*)0;
}
/*主函数*/
int main(void)
{
int err;
pthread_t rth, wth;
Storage s;
s.r_wait = 0;
s.w_wait = 0;
pthread_mutex_init(&s.rm, NULL);
pthread_mutex_init(&s.wm, NULL);
pthread_cond_init(&s.rc, NULL);
pthread_cond_init(&s.wc, NULL);
//创建一个读者线程和写者线程
err = pthread_create(&rth, NULL,get_th, (void*)&s);
if(err)perror("pthread create error");
err = pthread_create(&wth, NULL,set_th, (void*)&s);
if(err)perror("pthread create error");
pthread_join(rth,NULL);
pthread_join(wth,NULL);
pthread_mutex_destroy(&s.rm);
pthread_mutex_destroy(&s.wm);
pthread_cond_destroy(&s.rc);
pthread_cond_destroy(&s.wc);
return 0;
}
- 输出
0xb6559460(1 ) write data: 101
0xb6d5a460(1 ) read data: 101
0xb6559460(2 ) write data: 102
0xb6d5a460(2 ) read data: 102
0xb6559460(3 ) write data: 103
0xb6d5a460(3 ) read data: 103
0xb6559460(4 ) write data: 104
0xb6d5a460(4 ) read data: 104
0xb6559460(5 ) write data: 105
0xb6d5a460(5 ) read data: 105
0xb6559460(6 ) write data: 106
0xb6d5a460(6 ) read data: 106
0xb6559460(7 ) write data: 107
0xb6d5a460(7 ) read data: 107
0xb6559460(8 ) write data: 108
0xb6d5a460(8 ) read data: 108
0xb6559460(9 ) write data: 109
0xb6d5a460(9 ) read data: 109
0xb6559460(10 ) write data: 110
0xb6d5a460(10 ) read data: 110
以上是关于Linux练习_线程练习_读者写者问题的主要内容,如果未能解决你的问题,请参考以下文章
Linux多线程_(线程池,单例模式,读者写者问题,自旋锁)