课时78_互斥锁实现线程同步
1、代码示例
#include <stdio.h> //printf对应的头文件
#include <unistd.h> //usleep对应的头文件
#include <pthread.h> //线程对应的头文件
//宏定义,每个线程操作全局变量number次数
#define COUNT_MAX 10000
//全局变量
int number;
//创建一把互斥锁,全局变量
pthread_mutex_t mutex;
//子线程pthid_p1,操作全局变量number
void* pthid_p1_func(void* arg)
{
for(int i=0;i<COUNT_MAX;++i)
{
//访问共享资源(全局变量number)前加锁
//如果mutex被锁上了,代码阻塞在当前位置,从而不能执行对全局变量number操作的函数,防止了数据混乱
pthread_mutex_lock(&mutex);
//number++;
int current = number;
current++;
number = current; //取值自增后赋值,cpu与物理内存之间的存取
printf("Pthread_p1,pth_id:%lu,number:%d\n",pthread_self(),number);
//访问共享资源(全局变量number)后解锁
pthread_mutex_unlock(&mutex);
//usleep主动放弃cpu,模拟cpu被抢占
usleep(100);
}
return NULL;
}
//子线程pthid_p2,操作全局变量number
void* pthid_p2_func(void* arg)
{
for(int i=0;i<COUNT_MAX;++i)
{
//访问共享资源(全局变量number)前加锁
//如果mutex被锁上了,代码阻塞在当前位置,从而不能执行对全局变量number操作的函数,防止了数据混乱
pthread_mutex_lock(&mutex);
int current = number;
current++;
number = current; //取值自增后赋值,cpu与物理内存之间的存取
printf("Pthread_p2,pth_id:%lu,number:%d\n",pthread_self(),number);
//访问共享资源(全局变量number)后解锁
pthread_mutex_unlock(&mutex);
//usleep主动放弃cpu,模拟cpu被抢占
usleep(100);
}
return NULL;
}
//主函数
int main()
{
//子线程ID
pthread_t pthid_p1,pthid_p2;
//初始化互斥锁
pthread_mutex_init(&mutex, NULL);
//创建子线程
pthread_create(&pthid_p1,NULL,pthid_p1_func,NULL);
pthread_create(&pthid_p2,NULL,pthid_p2_func,NULL);
//阻塞,资源回收
pthread_join(pthid_p1,NULL);
pthread_join(pthid_p2,NULL);
//释放互斥锁
pthread_mutex_destroy(&mutex);
return 0;
}
2、执行结果
Pthread_p1,pth_id:140620953962240,number:19996
Pthread_p2,pth_id:140620945569536,number:19997
Pthread_p1,pth_id:140620953962240,number:19998
Pthread_p1,pth_id:140620953962240,number:19999
Pthread_p1,pth_id:140620953962240,number:20000
root@Ubuntu18:/home/remotefs/001.Linux_sys#
3、分析总结—加锁的思想
加锁的思想:
(1)通过判断锁的状态来决定是否执行pthread_mutex_lock
和pthread_mutex_unlock
两个函数之间的代码(临界区)。从而阻塞线程中特定的代码片段执行(一般是操作共享资源)。使线程对共享资源的访问变为串行访问(包括读和写),从而防止数据混乱。
(2)模拟原子操作。
原子操作:cpu在处理一个指令,线程/进程在处理完这个指令之前是不会失去cpu的。
版权声明:本文为sznari2012原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。