Linux多线程编程:线程同步与互斥之一--互斥锁mutex

如果在某一时刻值只允许一个线程来访问某部分资源,保证共享数据操作的完整性,那么这种操作就成为互斥。互斥锁的作用就是对这种临界区进行保护,内部是对一个变量的原子操作(置0或置1)来决定能否获得锁来访问。

1、初始化

可以直接在定义时进行静态初始化

pthread_mutex_t  g_tMutex  = PTHREAD_MUTEX_INITIALIZER;

或者调用pthread_mutex_init函数动态初始化为NULL:

int pthread_mutex_init(pthread_mutex_t *restrict mutex, 
					   const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);

2、加锁与解锁API函数

int pthread_mutex_lock(pthread_mutex_t *mutex);		// 一直等待到可用
int pthread_mutex_trylock(pthread_mutex_t *mutex);	// 立即返回(EBUSY)或加锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);	// 释放互斥量

3、示例

先看不加锁的线程操作:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

int i = 0;

void *pthreadFunc(void *pvoid)
{
	while(i < 200)
	{
		printf("pthreadFunc %s: %d\n", (char *)pvoid, i++);	// 改变变量的值
		usleep(500);
	}
	pthread_exit(NULL);
}


int main()
{
	pthread_t tid[2];

	pthread_create(&tid[0], NULL, pthreadFunc, "0");
	pthread_create(&tid[1], NULL, pthreadFunc, "1");

	pthread_join(tid[0], NULL);
	pthread_join(tid[1], NULL);
	
	return 0;
}

编译运行一下查看结果(这里抽取异常的一部分):

pthreadFunc 0: 0
pthreadFunc 1: 1
pthreadFunc 0: 2
pthreadFunc 1: 3
pthreadFunc 0: 5
pthreadFunc 1: 4
pthreadFunc 0: 6
pthreadFunc 1: 7
pthreadFunc 1: 8
pthreadFunc 0: 9
pthreadFunc 0: 10
pthreadFunc 1: 11
pthreadFunc 1: 12
pthreadFunc 0: 13
pthreadFunc 0: 14
pthreadFunc 1: 14
pthreadFunc 1: 15
pthreadFunc 0: 16
pthreadFunc 1: 17
pthreadFunc 0: 18
pthreadFunc 1: 19
pthreadFunc 0: 20
pthreadFunc 0: 21
pthreadFunc 1: 21

从输出结果可以看到,在4、5、14、21几个位置出现了顺序或重复的错误,这是因为两个线程同时对共享数据 i 进行操作导致的。所以针对这种情况,可以引入互斥锁改进程序:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

int i = 0;
pthread_mutex_t g_Mutex  = PTHREAD_MUTEX_INITIALIZER;

void *pthreadFunc(void *pvoid)
{
	while(i < 200)
	{
		pthread_mutex_lock(&g_Mutex);	// 加锁之后其他线程需要等到解锁才能对同一把锁上锁,否则阻塞等待
		printf("pthreadFunc %s: %d\n", (char *)pvoid, i++);	// 改变变量的值
		usleep(500);
		pthread_mutex_unlock(&g_Mutex);	// 解锁,其他线程可以对这个锁加锁了
	}
	pthread_exit(NULL);
}


int main()
{
	pthread_t tid[2];

	pthread_create(&tid[0], NULL, pthreadFunc, "0");
	pthread_create(&tid[1], NULL, pthreadFunc, "1");

	pthread_join(tid[0], NULL);
	pthread_join(tid[1], NULL);
	pthread_mutex_destroy(&g_Mutex);
	
	return 0;
}

再次编译运行可以看到程序不会出现顺序或者重复的情况了,因为 i 的值在某个时刻只有一个线程在操作。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

R-QWERT

你的鼓励是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值