版权声明:如有需要,可供转载,但请注明出处:https://blog.csdn.net/City_of_skey/article/details/85494572

 

目录

1、简介

2、API

2.1 pthread_mutex_init

2.2 pthread_mutex_lock

2.3 pthread_mutex_trylock

2.4 pthread_mutex_timedlock

3.5 pthread_mutex_unlock

2.6 pthread_mutex_destroy

3、例子

4、比较


1、简介

linux多线程的环境中为了保证变量的同步需要使用互斥锁mutex,当一个线程使用互斥锁时,另一个线程就会阻塞进入睡眠状态。互斥锁本质上是信号量的一个特例,信号量是可以多个线程共享资源,而互斥锁同时只能一个进程使用资源。互斥锁不能使用在中断因为中断不能休眠。互斥锁也不能递归

2、API

2.1 pthread_mutex_init

互斥锁的初始化有两种:动态初始化、静态初始化,动态初始化调用pthread_mutex_init,一般默认是缺省模式所以,第二个参数是NULL,

pthread_mutex_init(&lock, NULL)

静态初始化是调用宏 PTHREAD_MUTEX_INITIALIZER

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER

2.2 pthread_mutex_lock

这个函数就会加锁,如果已经被锁住那么线程就会阻塞进入休眠,如果加锁成功那么其他进程就不能就会进入阻塞休眠状态。

2.3 pthread_mutex_trylock

这个函数在Pthread_mutex_lock的基础上做了改进,调用该函数如果没有获取锁就会返回EBUSY错误码,表示该锁已经被其他线程占用,立即返回而不是进入阻塞状态。

2.4 pthread_mutex_timedlock

pthread_mutex_timedlock是在pthread_mutex_lock的基础上添加了超时时间,如果超过了这个时间还没有获取锁就返回,返回错误码ETIMEDOUT,第二个参数是超时时间变量struct timespec abs_timeout。

struct timespec abs_timeout;
abs_timeout.tv_sec = time(NULL) + 1;
abs_timeout.tv_nsec = 0;

3.5 pthread_mutex_unlock

释放锁

2.6 pthread_mutex_destroy

销毁互斥锁,释放空间。

3、例子

不加互斥锁:

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

int g_val = 0;

void *fun1(void *argv){
	int i = 0;	
	for(i = 0; i < 10000; ++i){
		g_val += 1;
	}
}


int main(){
	
	pthread_t t1, t2;	
	
	pthread_create(&t1, NULL, fun1, NULL);
	pthread_create(&t2, NULL, fun1, NULL);
	pthread_join(t1, NULL);
	pthread_join(t2, NULL);
	
	printf("g_val:%d\n", g_val);
}

运行结果:

root@ubuntu:/home/c_test/mutex# ./a.out
g_val:20000
root@ubuntu:/home/c_test/mutex# ./a.out
g_val:19839
root@ubuntu:/home/c_test/mutex# ./a.out
g_val:11580
root@ubuntu:/home/c_test/mutex# ./a.out
g_val:20000
root@ubuntu:/home/c_test/mutex# ./a.out
g_val:20000

因为两个线程同时对全局变量g_val做加的操作而没有加锁,最终g_val的值是不确定的。

 

加互斥锁:

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int g_val = 0;

void *fun1(void *argv){
	int i = 0;	
	for(i = 0; i < 10000; ++i){
		pthread_mutex_lock(&lock);
		g_val += 1;
		pthread_mutex_unlock(&lock);
	}
}


int main(){
	
	pthread_t t1, t2;	
	
	pthread_create(&t1, NULL, fun1, NULL);
	pthread_create(&t2, NULL, fun1, NULL);
	pthread_join(t1, NULL);
	pthread_join(t2, NULL);
	pthread_mutex_destroy(&lock);
	printf("g_val:%d\n", g_val);
}

运行结果:

root@ubuntu:/home/c_test/mutex# ./a.out
g_val:20000
root@ubuntu:/home/c_test/mutex# ./a.out
g_val:20000
root@ubuntu:/home/c_test/mutex# ./a.out
g_val:20000
root@ubuntu:/home/c_test/mutex# ./a.out
g_val:20000
root@ubuntu:/home/c_test/mutex# ./a.out
g_val:20000

加了互斥锁后每次运行结果都是20000.

4、比较

1、当没有获取锁时互斥锁就会阻塞进入休眠状态,但自旋锁不会休眠会一致在等待,如果资源锁定时间短用自旋锁的效率更高,内核开发中使用自旋锁比较多,但如果资源锁定时间长建议使用互斥锁。自旋锁不会休眠如果资源要休眠建议使用互斥锁、信号量。

2、互斥锁和信号量先比互斥锁占用空间比信号量小,效率比信号量高。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐