Linux系统编程读写锁和条件变量使用
文章目录
1.读写锁概念
2.条件变量的概念和使用
1.读写锁概念
1.读写锁的适用场景?
互斥锁- - -读写串行
读写锁- - -:
读: 并行
写:串行
程序中的读操作大于写操作的时候
2.代码展示
创建三个写线程,创建五个读线程
为了防止数据混乱(CPU调度问题)
需要给共享资源上锁,保证数据的整齐
使用读写锁
#include
#include
#include
#include
#include
int number=0;
//创建读写锁
pthread_rwlock_t lock;
void* write_func(void* arg) {
//循环写
while(1) {
pthread_rwlock_wrlock(&lock);
number++;
printf("==write:%lu,%d\n",pthread_self(),number);
//解锁
pthread_rwlock_unlock(&lock);
sleep(1);
}
return NULL;
}
void* read_func(void* arg) {
while(1) {
//加读锁
pthread_rwlock_rdlock(&lock);
printf("==read:%lu,%d\n",pthread_self(),number);
pthread_rwlock_unlock(&lock);
sleep(1);
}
return NULL;
}
int main()
{
pthread_t p[8];
pthread_rwlock_init(&lock,NULL);
//循环创建三个写线程
int i=0;
for(i=0;i<3;++i) {
pthread_create(&p[i],NULL,write_func,NULL);
}
//创建五个度线程
int j=0;
for(j=3;j<8;++j) {
pthread_create(&p[j],NULL,read_func,NULL);
}
//阻塞回收子线程的pcb
i=0;
for(i=0;i<8;++i) {
pthread_join(p[i],NULL);
}
//释放读写锁资源
pthread_rwlock_destroy(&lock);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
2.条件变量的概念和使用
1.条件变量的两个动作
条件不满足,阻塞线程
当条件满足,通知阻塞的线程开始工作
条件变量的类型
1. pthread_cond_t cond;
1
主要函数
①初始化一个条件变量–condition;
1. pthread_cond_init(pthread_cond_t* restrict cond,
const pthread_condattr_t* restrict attr);
1
2
②销毁一个条件变量
1. pthread_cond_destroy(pthread_cond_t* cond);
1
③阻塞等待一个条件变量
1. pthread_cond_wait(pthread_cond_t* restrict cond,
pthread_mutex_t* restrict mutex);
1
2
阻塞线程
将已经上锁的mutex解锁
该函数解除阻塞,会对互斥锁加锁
④限时等待一个条件变量—阻塞一定的时长
1. pthread_cond_timedwait(pthread_cond_t* restrict cond,
pthread_mutex_t* restrict mutex,
const struct timespaec *restrict abstime);
1
2
3
⑤唤醒至少一个阻塞在条件变量上的线程
1. pthread_cont_signal(pthread_cond_t* cond);
1
⑥唤醒全部阻塞在条件变量上的线程
1. pthread_cond_broadcast(pathread_cond_t* cond);
1
代码展示
条件变量的使用常常会搭配着互斥锁一起使用
互斥锁- - - - -保护共享资源
条件变量- - - - 对线程的阻塞作用(条件不满足则阻塞,条件满足则不再阻塞)
#include
#include
#include
#include
#include
#include
//--------------------------全局参数设定-----------------------
//创建结点结构
typedef struct node {
int data;
struct node* next;
}node;
//定义指向链表头部的指针
node* head=NULL;
//线程同步---互斥锁
pthread_mutex_t mutex;
//阻塞线程
pthread_cond_t cond;
//--------------------------生产者操作----------------------
void* wr_func(void* arg) {
while(1) {
//创建一个链表的结点
node* pnew=(node*)malloc(sizeof(node));
//节点的初始化
pnew->data=rand()%1000;
//使用互斥锁保护共享资源
pthread_mutex_lock(&mutex);
//指针域
pnew->next=head;
head=pnew;
printf("=====生产:%lu,%d\n",pthread_self(),pnew->data);
pthread_mutex_unlock(&mutex);
//通知阻塞的线程解除阻塞
pthread_cond_signal(&cond);
sleep(rand()%3);
}
return NULL;
}
//---------------------消费者操作---------------------
void* rd_func(void* arg) {
while(1) {
pthread_mutex_lock(&mutex);
//判断链表是否为空
if(head==NULL) {
//线程阻塞
//该函数会对互斥锁解锁
pthread_cond_wait(&cond,&mutex);
//解除阻塞后,对互斥锁做加锁操作
}
//链表不为空
//产生消费行为,删除头结点
node* Pple=head;
head=head->next;
printf("-----消费者: %lu,%d\n",pthread_self(),Pple->data);
free(Pple);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
//---------------------------main函数主函数----------------------------
int main()
{
pthread_t p1,p2;
//初始化
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
//创建生产者线程
pthread_create(&p1,NULL,wr_func,NULL);
//创建消费者线程
pthread_create(&p2,NULL,rd_func,NULL);
//阻塞回收线程
pthread_join(p1,NULL);
pthread_join(p2,NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}