互斥量的引入:
很多变量在线程间共享,通过数据的共享完成线程之间的交互
解决多个线程并发的操作共享变量带来的问题
互斥量实现的要求:
1 当代码进入临界区,不允许其他线程进入该临界区
2 若线程不在临界区执行,该线程不能阻止其他线程进入临界区
3 多线程同时要求执行临界区代码,且临界区没线程执行,则允许一个线程进入临界区
互斥量相关函数
初始化:
静态分配:pthread_mutex_t mutex
动态分配:pthread_mutex_init
互斥量加锁:
pthread_mutex_lock
互斥量解锁
pthread_mutex_unlock
互斥量销毁
pthread_mutex_destroy
互斥量加锁注意:
1 互斥量处于未锁状态,函数将互斥量锁定,返回成功。
2 发起函数调用时,其他线程已经锁定,或其他线程同时申请互斥量,
但没有竞争到互斥量,那么pthread_lock调用会陷入阻塞,等待互斥量解锁
互斥量销毁注意:
1 使用静态分配初始化的互斥量不需要销毁
2 不要销毁一个已经加锁的互斥量
3 已销毁的互斥量确保后面不会线程再尝试加锁
改进版售票系统
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<sched.h>
int ticket=100;
pthread_mutex_t mutex; //定义互斥量
void* route(void *arg)
{
char *id=(char*)arg;
while(1)
{
pthread_mutex_lock(&mutex);//互斥量加锁
if(ticket>0)
{
usleep(10000);
printf("%s sells ticket: %d\n",id,ticket);
ticket--;
pthread_mutex_unlock(&mutex); //互斥量解锁
}
else
{
pthread_mutex_unlock(&mutex);//互斥量解锁,退出
break;
}
}
}
int main()
{
pthread_t t1, t2, t3, t4;
pthread_mutex_init(&mutex,NULL);
pthread_create(&t1,NULL,route,"pthread1");//创建线程 1,2,3,4,
pthread_create(&t2,NULL,route,"pthread2");
pthread_create(&t3,NULL,route,"pthread3");
pthread_create(&t4,NULL,route,"pthread4");
pthread_join(t1,NULL); //线程1,2,3,4,等待
pthread_join(t2,NULL);
pthread_join(t3,NULL);
pthread_join(t4,NULL);
pthread_mutex_destroy(&mutex); //销毁互斥量
}
条件变量的引入
描述资源就绪与否的状态,为实现同步(协调多线程之间的饥饿问题)而引入。
函数接口
pthread_cond_init 条件变量初始
pthread_cond_destroy 条件变量销毁
pthread_cond_wait 等待条件满足
即:解锁互斥量并等待条件变量触发
pthread_cond_signal 唤醒等待
即:唤醒条件变量等待的上一个线程
pthread_cond_broadcast 唤醒等待
即:唤醒条件变量等待的上一个线程
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
pthread_cond_t cond; //声明条件变量
pthread_mutex_t mutex; //声明互斥量
void* r1(void* arg)
{
while(1)
{
printf("传球!\n");
pthread_cond_signal(&cond); //唤醒等待
usleep(789123);
}
return NULL;
}
void* r2(void* arg)
{
while(1)
{
pthread_cond_wait(&cond,&mutex); //条件变量等待
printf("投篮!\n");
usleep(123456);
}
return NULL;
}
int main(void)
{
pthread_t t1, t2;
pthread_cond_init(&cond,NULL); //初始化条件变量
pthread_mutex_init(&mutex,NULL); //初始化互斥量
pthread_create(&t1,NULL,r1,NULL);//创建线程1,2
pthread_create(&t2,NULL,r2,NULL);
pthread_join(t1,NULL);//线程1,2等待
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex);//销毁互斥量
pthread_cond_destroy(&cond);//销毁条件变量
return 0;
}