1.mutex互斥锁
常用的互斥锁函数
pthread_mutex_init(3) #初始化锁,返回0
pthread_mutex_destroy(3) #指定要销毁锁的地址,成功返回0
pthread_mutex_lock(3) # 如果锁被其他线程占用,阻塞等待,直到占用该锁的线程释放锁。否则,立即上锁并返回
pthread_mutext_trylock(3) #尝试加锁,如不能,返回错误。可以,立即加锁并返回
pthread_mutext_unlock(3) #释放锁
代码实现,两个线程交替计算
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<sys/types.h>
pthread_mutex_t mutex;
int value = 0;
void *temp(void *arg){
int tmp;
for(int i = 0; i < 5000; i++){
//lock now
pthread_mutex_lock(&mutex);
tmp = value;
tmp++;
printf("threadId: %lu\ttmp = %d\n", pthread_self(), tmp);
value = tmp;
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(void){
pthread_mutex_init(&mutex, NULL);
pthread_t thread_1, thread_2;
pthread_create(&thread_1, NULL, temp, NULL);
pthread_create(&thread_2, NULL, temp, NULL);
pthread_join(thread_1, NULL);
pthread_join(thread_2, NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
2.条件变量
常用函数
pthread_cond_init(3) #初始化一个条件变量
pthread_cond_destroy(3) # 销毁条件变量的地址
pthread_cond_signal(3) # 如果有多个线程等待条件变量为真,从其中选出一个执行。如果没有线程等待条件变量为真,什么都不做。
pthread_cond_broadcast(3) #通知多个有等待条件变量为真的线程执行。如果没有条件变量为真,则什么都不做。
pthread_cond_wait(3) # 原子的解锁并等待条件变量为真。当条件变量为真的时候,重新获取mutex锁
pthread_cond_timewait(3)
生产者消费者模型
#include <t_stdio.h>
#include <pthread.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
//定义链表节点的类型
typedef struct node{
int data;
struct node *next;
}node_t;
node_t *head=NULL;
pthread_mutex_t mutex;//定义锁类型的变量
pthread_cond_t cond;//定义条件变量
//生产者线程
void *product(void *arg){
node_t *new;
while(1){
//生产一个新节点
new=(node_t *)malloc(sizeof(node_t));
new->data=rand()%1000+1;
new->next=NULL;
printf("p:%d\n",new->data);
//加锁
pthread_mutex_lock(&mutex);
new->next=head;
head=new;
//解锁
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
sleep(rand()%3+1);
}
return NULL;
}
//消费者线程
void *consume(void *arg){
node_t *tmp;
while(1){
//加锁
pthread_mutex_lock(&mutex);
while(head==NULL)
pthread_cond_wait(&cond,&mutex);
//重新获取mutex锁
tmp=head;
head=head->next;
//解锁
pthread_mutex_unlock(&mutex);
printf("c:%d\n",tmp->data);
//消费该节点
free(tmp);
tmp=NULL;
sleep(rand()%3+1);
}
return NULL;
}
int main(void){
srand(time(NULL));
//初始化mutex变量
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
//创建两个线程 生产者 消费者
pthread_t pid,cid;
pthread_create(&pid,NULL,product,NULL);
pthread_create(&cid,NULL,consume,NULL);
//等待线程的汇合
pthread_join(pid,NULL);
pthread_join(cid,NULL);
//销毁mutex变量
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
3.信号量
常用的函数
sem_init # 初始化一个匿名的信号量
sem_destroy # 销毁信号量
sem_post # 解锁信号量,信号量+1,如果有线程或者进程调用阻塞在该信号量,则被唤醒,继续锁定信号量(-1)
sem_wait # 信号量值减1操作。如果当前信号量的值为0,阻塞等待直到其他进程或线程使该信号量大于0为止
sem_trywait # 尝试一次操作,如果信号量的值为0,立即返回,返回错误
sem_timedwait # 指定等待的时间,超时返回超时错误
信号量控制的生产者和消费者模型
#include <pthread.h>
#include <t_stdio.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <semaphore.h>
typedef int que_t[7];
sem_t p,c;
que_t que;//定义队列
//生产者线程
void *product(void *arg){
int index=0;
while(1){
sem_wait(&p);//如果p的值=0,阻塞
que[index]=rand()%500+1;
printf("p:%d\n",que[index]);
index=(index+1)%7;
sem_post(&c);//可消费的数量加1
sleep(rand()%3+1);
}
}
//消费者线程
void *consume(void *arg){
int index=0;
int tmp;
while(1){
sem_wait(&c);
tmp=que[index];
que[index]=-1;
printf("c:%d\n",tmp);
index=(index+1)%7;
sem_post(&p);//可生产数量加1
sleep(rand()%3+1);
}
}
int main(void){
srand(time(NULL));
//初始化信号量
sem_init(&p,0,7);
sem_init(&c,0,0);
//创建两个线程,分别用于生产者和消费者
pthread_t pid,cid;
pthread_create(&pid,NULL,product,NULL);
pthread_create(&cid,NULL,consume,NULL);
//阻塞等待线程汇合
pthread_join(pid,NULL);
pthread_join(cid,NULL);
//销毁信号量
sem_destroy(&p);
sem_destroy(&c);
return 0;
}
网友评论