Linux系统编程_课时78_互斥锁实现线程同步

课时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_lockpthread_mutex_unlock两个函数之间的代码(临界区)。从而阻塞线程中特定的代码片段执行(一般是操作共享资源)。使线程对共享资源的访问变为串行访问(包括读和写),从而防止数据混乱。
(2)模拟原子操作。
原子操作:cpu在处理一个指令,线程/进程在处理完这个指令之前是不会失去cpu的。


版权声明:本文为sznari2012原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。