3.7.6.1、什么是互斥锁
(1)互斥锁又叫互斥量(mutex)
(2)相关函数:
pthread_mutex_init 初始化互斥锁
pthread_mutex_destroy 删除互斥锁
pthread_mutex_lock 互斥锁 上锁
pthread_mutex_unlock 互斥锁 解锁
(3)互斥锁和信号量的关系:可以认为互斥锁是一种特殊的信号量
(4)互斥锁主要用来实现关键段保护: 保证当前线程 访问时,不允许其他线程访问
注意:man pthread_mutex_init时提示找不到函数,说明你没有安装pthread相关的man手册。安装方法:1、虚拟机上网;2、sudo apt-get install manpages-posix-dev
3.7.6.2、用互斥锁来实现上节的代码
#include
#include
#include
#include
#include
char buf[200] = {0};
pthread_mutex_t mutex; /* 定义一个互斥锁 mutex */
int flag = 0;
//子线程程序,作用是统计 buf 的个数 和 显示
void *func(void *arg)
{
// 子线程首先应该有个循环
// 循环中阻塞在等待主线程激活的时候,子线程被激活后就去获取buf中的字符
// 长度,然后打印;完成后再次被阻塞
sleep(1);
while(flag == 0)
{
pthread_mutex_lock(&mutex); /* 互斥量 上锁 */
printf("本次输入了%d个字符\n", strlen(buf));
memset(buf, 0, sizeof(buf));
pthread_mutex_unlock(&mutex);/* 互斥量 解锁 */
sleep(1);
}
printf("跳出 while死循环 \n");
pthread_exit(NULL); /* 退出子线程 */
}
int main()
{
int ret =-1;
pthread_t th = -1;
/*初始化 互斥量 */
pthread_mutex_init(&mutex, NULL);
/* pthread_create 创建 子线程 */
ret = pthread_create(&th,NULL,func, NULL);/* pthread_create 创建线程成功 返回0 */
if(ret != 0)
{
printf("pthread_create error \n");
exit(-1);
}
printf("输入一个字符串,以回车结束 \n");
while(1)
{
pthread_mutex_lock(&mutex);/* 互斥量 上锁 */
scanf("%s",buf);
pthread_mutex_unlock(&mutex);/* 互斥量 解锁 */
//去 比较 用户输入的是不是 end ,如果是 则退出,如果不是则继续
if(!strncmp(buf, "end", 3))/* strncmp :字符比较函数,如果相等 返回0 */
{
printf("程序结束 \n");
flag = 1;
break; /* 直接跳出 while 循环 */
}
sleep(1);
// 主线程在收到用户收入的字符串,并且确认不是end后
// 就去发信号激活子线程来计数。
// 子线程被阻塞,主线程可以激活,这就是线程的同步问题。
// 信号量就可以用来实现这个线程同步
}
printf("等待回收子线程\n");
//回收子线程
ret = pthread_join(th,NULL);
if(ret != 0)
{
printf("pthread_join error \n");
exit(-1);
}
printf("子线程回收成功\n");
pthread_mutex_destroy(&mutex); /*删除 互斥锁 */
return 0;
}
运行结果:
注意: 互斥锁 不是 阻塞的, 只是 上锁一次, 就要解锁 一次,
我自己理解的!!!
3.7.7.线程同步之条件变量
3.7.7.1、什么是条件变量: 条件变量 跟 互斥锁 有关系的 ,
3.7.7.2、相关函数
pthread_cond_init 初始化 条件变量
pthread_cond_destroy 删除 条件变量
pthread_cond_wait 等待 条件变量
pthread_cond_signal/pthread_cond_broadcast 这两个都是 唤醒 条件变量
signal: 只唤醒一个 条件变量
broadcas: 广播 唤醒很多条件变量
3.7.7.3、使用条件变量来实现上节代码 : 效率高 , 没有 sleep
#include
#include
#include
#include
#include
char buf[200] = {0};
pthread_mutex_t mutex; /* 定义一个互斥锁 mutex */
pthread_cond_t cond; /* 定义一个条件变量 cond */
int flag = 0;
//子线程程序,作用是统计 buf 的个数 和 显示
void *func(void *arg)
{
// 子线程首先应该有个循环
// 循环中阻塞在等待主线程激活的时候,子线程被激活后就去获取buf中的字符
// 长度,然后打印;完成后再次被阻塞
while(flag == 0)
{
pthread_mutex_lock(&mutex); /* 互斥量 上锁 */
pthread_cond_wait(&cond, &mutex); /* 等待 条件变量 发信号, 必须要加 互斥锁 */
printf("本次输入了%d个字符\n", strlen(buf));
memset(buf, 0, sizeof(buf));
pthread_mutex_unlock(&mutex);/* 互斥量 解锁 */
}
printf("跳出 while死循环 \n");
pthread_exit(NULL); /* 退出子线程 */
}
int main()
{
int ret =-1;
pthread_t th = -1;
/*初始化 互斥量 */
pthread_mutex_init(&mutex, NULL);
/*初始化 条件变量 cond */
pthread_cond_init(&cond, NULL);
/* pthread_create 创建 子线程 */
ret = pthread_create(&th,NULL,func, NULL);/* pthread_create 创建线程成功 返回0 */
if(ret != 0)
{
printf("pthread_create error \n");
exit(-1);
}
printf("输入一个字符串,以回车结束 \n");
while(1)
{
//pthread_mutex_lock(&mutex);/* 互斥量 上锁 */
scanf("%s",buf);
pthread_cond_signal(&cond);
//pthread_mutex_unlock(&mutex);/* 互斥量 解锁 */
//去 比较 用户输入的是不是 end ,如果是 则退出,如果不是则继续
if(!strncmp(buf, "end", 3))/* strncmp :字符比较函数,如果相等 返回0 */
{
printf("程序结束 \n");
flag = 1;
break; /* 直接跳出 while 循环 */
}
//sleep(1);
// 主线程在收到用户收入的字符串,并且确认不是end后
// 就去发信号激活子线程来计数。
// 子线程被阻塞,主线程可以激活,这就是线程的同步问题。
// 信号量就可以用来实现这个线程同步
}
printf("等待回收子线程\n");
//回收子线程
ret = pthread_join(th,NULL);
if(ret != 0)
{
printf("pthread_join error \n");
exit(-1);
}
printf("子线程回收成功\n");
pthread_mutex_destroy(&mutex); /*删除 互斥锁 */
pthread_cond_destroy(&cond); /*删除 条件变量 */
return 0;
}
运行结果:
3.7.7.4、线程同步总结