参考学习资料:进程线程互斥与同步
1.信号量
mutex初始化后为0;上锁后+1,解锁后-1;mutex只能串行。
信号量可以并行,运行多个线程同时访问共享资源。
1.1 头文件
#include <semaphore.h>
1.2 变量类型
//类型名 变量名
sem_t sem;
1.3 主要函数
(1)初始化信号量
sem_init(sem_t* sem,
int pshared, //0-线程同步;1-进程同步
unsigned int value);//最多有几个线程共享操作数据
(2) 销毁信号量
sem_destroy(sem_t* sem);
(3) 加锁
sem_wait(sem_t* sem);
调用一次相当于对sem做--(减减)操作,如果value=5,最多5个线程。
如果sem值为0,线程会阻塞。
(4) 尝试加锁
sem_trywait(sem_t* sem);
sem==0,加锁失败,不阻塞,直接返回。
(5) 限时尝试加锁
sem_timedwait(sem_t* sem,xxxx);
(6)解锁
sem_post(sem_t* sem);
对sem进行++操作。
2. 代码示例(C语言)
//消费者,生产者模型
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include <windows.h>
#include <semaphore.h>
//创建节点的结构
typedef struct node{
int data;
struct node* next;
}Node;
//定义一个指针,指向链表头部
Node* head=NULL;
//定义两个信号量
sem_t customer_sem, producer_sem;
//生产者
void* producer(void* arg){
while(1){
//使用信号量 完成线程的阻塞
sem_wait(&producer_sem);
//创建一个链表的节点
Node* pnew=(Node*)malloc(sizeof(Node));
//节点初始化
pnew->data=rand()%1000;
pnew->next=head;
head=pnew;//节点被插入到链表头部
printf("===== produce: %lu, %d\n",pthread_self(),pnew->data);
sem_post(&customer_sem);//customer_sem++
sleep(rand()%5);
}
return NULL;
}
void* customer(void* arg){
while(1){
sem_wait(&customer_sem);//==0阻塞
//链表不为空,删除头节点
Node* pdel=head;
head=head->next;
printf("===== customer: %lu, %d\n",pthread_self(),pdel->data);
free(pdel);
sem_post(&producer_sem);
sleep(rand()%5);
}
return NULL;
}
int main(void){
int i=0;
pthread_t thrd[2];
sem_init(&customer_sem,0,0);
sem_init(&producer_sem,0,4);
//创建生产者线程
pthread_create(&thrd[0],NULL,producer,NULL);
pthread_create(&thrd[1],NULL,customer,NULL);
//阻塞回收
for(;i<2;i++){
pthread_join(thrd[i],NULL);
}
//销毁信号量
sem_destroy(&customer_sem);
sem_destroy(&producer_sem);
return 0;
}