1.互斥量
a)互斥量(mutex)从本质上来说是一把锁,一般在主线程中定义一个互斥量,就是定义一把锁。然后根据我们的需求来对线程操作这把锁。
b)如果给所有的线程都加上锁了,线程们会去争取内存空间,谁先争取到谁先运行,直到该线程解锁后,期间其他线程只能等待阻塞。
c)因为主线程不上锁,在先拿到锁的线程在跑的过程中,主线程也会跟着跑。
include <pthread.h>
// 返回:若成功返回0,否则返回错误编号
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);创建锁
int pthread_mutex_lock(pthread_mutex_t *mutex);//加锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);//销毁锁
互斥量用pthread_mutex_t数据类型表示。在使用互斥量前必须对它进行初始化,可以通过调用pthread_mutex_init函数进行初始化。如果动态地分配互斥量(例如通过调用malloc函数),那么在释放内存前需要调用 pthread_mutex_destroy.
要用默认的属性初始化互斥量,只需要把attr设置为NULL。
锁:如果线程不希望被阻塞,它可以使用pthread_mutex_trylock尝试对互斥量进行加锁。如果调用pthread_mutex_trylock时互斥量处于未锁住状态,那么pthread_mutex_trylock将锁住互斥量,不会出现阻塞并返回0,否则pthread_mutex_trylock就会失败,不能锁住互斥量,而返回EBUSY。
2.加锁解锁简单操作:
代码:
#include<stdio.h>
#include<pthread.h>
#include <unistd.h>
int data = 0;//定义一个全局变量data
pthread_mutex_t mutex;//创建一把锁
void *func1(void *arg)
{
int i;
pthread_mutex_lock(&mutex);//加锁
for(i=0;i<5;i++){
printf("t1:thread id is:%ld\n",(unsigned long)pthread_self());
printf("t1:is param:%d\n",*((int *)arg));
sleep(1);
}
pthread_mutex_unlock(&mutex);//解锁
}
void *func2(void *arg)
{
pthread_mutex_lock(&mutex);//加锁
printf("t2:thread id is:%ld\n",(unsigned long)pthread_self());
printf("t2:is param:%d\n",*((int *)arg));
pthread_mutex_unlock(&mutex);//解锁
}
void *func3(void *arg)
{
pthread_mutex_lock(&mutex);//加锁
printf("t3:thread id is:%ld\n",(unsigned long)pthread_self());
printf("t3:is param:%d\n",*((int *)arg));
pthread_mutex_unlock(&mutex);//解锁
}
int main()
{
int ret;
int param = 100;
pthread_t t1;
pthread_t t2;
pthread_t t3;
pthread_mutex_init(&mutex,NULL);//初始化锁
ret = pthread_create(&t1,NULL,func1,(void *)¶m);//创建线程t1
if(ret == 0){
printf("main:创建线程t1成功!\n");
}
ret = pthread_create(&t2,NULL,func2,(void *)¶m);//创建线程t2
if(ret == 0){
printf("main:创建线程t2成功!\n");
}
ret = pthread_create(&t3,NULL,func3,(void *)¶m);//创建线程t3
if(ret == 0){
printf("main:创建线程t3成功!\n");
}
printf("main:获取主程序的ID:%ld\n",(unsigned long)pthread_self());
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_join(t3,NULL);
return 0;
}
结果:
先拿到锁的是t1线程先运行,但是会和主线程争抢内存,因为主线程没加锁,虽然会被打断,但是对于其他t2,t3线程,他们只有等待阻塞,等t1先运行完
3.互斥锁限制共享内存的访问
#include<stdio.h>
#include<pthread.h>
#include <unistd.h>
#include<stdlib.h>
int data = 0;//定义一个全局变量data
pthread_mutex_t mutex;
void *func1(void *arg)
{
pthread_mutex_lock(&mutex);
while(1){
printf("线程t1拿到 data = %d\n",data++);
sleep(1);
if(data == 5){
printf("t1:data = %d\n",data);
pthread_mutex_unlock(&mutex);
printf("=========t1线程退出============\n");
exit(0);
}
}
}
void *func2(void *arg)
{
while(1){
printf("线程t2拿到 data = %d\n",data);
pthread_mutex_lock(&mutex);
data++;
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main()
{
int ret;
int param = 100;
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&mutex,NULL);
ret = pthread_create(&t1,NULL,func1,(void *)¶m);//创建线程t1
if(ret == 0){
printf("main:创建线程t1成功!\n");
}
ret = pthread_create(&t2,NULL,func2,(void *)¶m);//创建线程t2
if(ret == 0){
printf("main:创建线程t2成功!\n");
}
printf("主线程main拿到data:%d\n",data);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
结果:
t2解锁后,t1一直拿锁,知道循环结束,整个程序退出,因为是共享内存。
4.死锁
前提条件是定义了两把锁,其中一个线程拿到了第一把锁和第二把锁,另外的一个线程拿到了第二把锁和第一把锁,然后他们都在争用锁的使用权,因为都解他们各自拥有的第一把所,所以一直卡在争用锁锁的使用权。
代码:
#include <stdio.h>
#include <pthread.h>
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
pthread_mutex_t mutex;
pthread_mutex_t mutex2;
int g_data=0;
void *func1(void *arg)
{
int i;
pthread_mutex_lock(&mutex);
sleep(1);
pthread_mutex_lock(&mutex2);
for(i=0;i<5;i++){
printf("t1:%ld thread is create\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int*)arg));
sleep(1);
}
pthread_mutex_unlock(&mutex);
}
void *func2(void *arg)
{
pthread_mutex_lock(&mutex2);
sleep(1);
pthread_mutex_lock(&mutex);
printf("t2:%ld thread is create\n",(unsigned long)pthread_self());
printf("t2:param is %d\n",*((int*)arg));
pthread_mutex_unlock(&mutex);
}
int main()
{
int ret;
int param=100;
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&mutex,NULL);
pthread_mutex_init(&mutex2,NULL);
ret=pthread_create(&t1,NULL,func1,(void*)¶m);
if(ret==0){
printf("main:create t1 success\n");
}
ret=pthread_create(&t2,NULL,func2,(void*)¶m);
if(ret==0){
printf("main:create t2 success\n");
}
printf("main %ld \n",(unsigned long)pthread_self());
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex);
pthread_mutex_destroy(&mutex2);
return 0;
}
结果:
main:create t1 success
main:create t2 success
main 139666438145792
^C
CLC@Embed_Learn:~/thread$ ./a.out
main:create t1 success
main:create t2 success
main 139839917381376
^C
CLC@Embed_Learn:~/thread$ ./a.out
main:create t1 success
main:create t2 success
main 139912974800640
^C
CLC@Embed_Learn:~/thread$
只有1把锁的情况下是不会造成死锁的
在这里func1拿着锁mutex,需要拿锁mutex2;func2拿着锁mutex2,需要拿锁mutex;从而造成了死锁。