linux下线程的同步与互斥-互斥锁

 1.作用
          跟前面学习的进程间通信信号量的作用一样,协调多个线程对于共享资源的访问
    2.三种方式协调多个线程对于共享资源的访问
          互斥锁
          条件变量
          信号量
    3.互斥锁
         (1)原理:多个线程要使用同一个共享资源,此时我们就需要用互斥锁协调多个线程对于共享资源的访问(保证任意时刻有且仅有一个线程在访问共享资源)
               比如:A和B两个线程,A线程上锁以后,A线程就能使用共享资源,此时B线程无法上锁,B线程会阻塞
                     等到A线程使用完共享资源之后,A线程解锁,解锁完毕,B线程才有机会上锁
            特点:多个线程使用同一把锁,谁先上锁,会导致后面上锁的线程全部阻塞
                  上锁和解锁操作需要成对使用,如果你的代码只有上锁,忘记解锁,会导致死锁现象
            死锁:线程上锁以后,忘记解锁,导致这把锁所有的线程都不能使用
                  常见的导致死锁的原因有如下两种
                         第一种:线程上锁以后,忘记解锁
                                 解决方法:自己把解锁代码写上去即可
                         第二种:线程上锁以后,被取消了,导致来不及解锁
                                 解决方法:一种是把线程设置成不可以取消
                                           另外一种是使用push和pop函数,在线程取消的时候解锁

         (2)相关的接口函数
                第一个:创建初始化互斥锁
                    pthread_mutex_t 互斥锁
                    pthread_mutex_t mymutex;
                    int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
                            参数:mutex --》互斥锁
                                  mutexattr --》互斥锁的属性,一般设置为NULL,表示使用默认属性
                第二个:使用互斥锁
                    int pthread_mutex_lock(pthread_mutex_t *mutex);   //上锁
                            参数:mutex --》你刚才初始化好的锁
                    int pthread_mutex_unlock(pthread_mutex_t *mutex); //解锁、开锁
                            参数:mutex --》你刚才初始化好的锁
                第三个:销毁互斥锁
                    int pthread_mutex_destroy(pthread_mutex_t *mutex);
                            参数:mutex --》你刚才初始化好的锁 

                注意:多个线程使用同一把锁,究竟谁先拿到锁(上锁)是随机(除非人为使用延时函数去干扰)
          (3)总结互斥锁使用的模型
                  某个线程1
                  {
                        //上锁

                           这一部分代码就是互斥锁需要保护的共享资源,确保任意时刻只有一个线程在使用共享资源

                       //解锁
                       //延时一丢丢,防止自己刚解锁,立马自己上锁
                  }

                  某个线程2
                  {
                        //上锁

                           这一部分代码就是互斥锁需要保护的共享资源,确保任意时刻只有一个线程在使用共享资源

                       //解锁
                       //延时一丢丢,防止自己刚解锁,立马自己上锁
                  }
线程刚上锁,来不及解锁就被取消啦,导致死锁

#include "myhead.h"

//定义一个全局变量表示目前库存数量
int num=0;

//定义一个互斥锁
pthread_mutex_t mymutex;

//用代码来模拟生产和销售

//生产者
void *product(void *arg)
{
	while(1)
	{
		//上锁
		pthread_mutex_lock(&mymutex);
		num++;
		printf("生产了一件产品,目前产品数量是:%d\n",num);
		sleep(5);
		//解锁
		pthread_mutex_unlock(&mymutex);
	}
}

//销售者
void *sale(void *arg)
{
	while(1)
	{
		//上锁
		pthread_mutex_lock(&mymutex);
		num--;
		printf("销售了一件产品,目前产品数量是:%d\n",num);
		sleep(5);
		//解锁
		pthread_mutex_unlock(&mymutex);
	}
}

int main()
{
	pthread_t id1,id2;
	
	//初始化互斥锁
	pthread_mutex_init(&mymutex,NULL);
	
	//创建两个线程--》分别表示生产部门和销售部门
	pthread_create(&id1,NULL,product,NULL); //生产部门
	pthread_create(&id2,NULL,sale,NULL);    //销售部门
	
	sleep(2);
	
	//干掉销售部门
	pthread_cancel(id2);
	
	//阻塞
	pthread_join(id1,NULL);
	pthread_join(id2,NULL);
	return 0;
}

解决线程刚上锁,就被取消导致死锁的现象

#include "myhead.h"

//定义一个全局变量表示目前库存数量
int num=0;

//定义一个互斥锁
pthread_mutex_t mymutex;

void fun(void *arg)
{
	printf("fun被调用了!\n");
	//解锁
	pthread_mutex_unlock(&mymutex);
}

//用代码来模拟生产和销售

//生产者
void *product(void *arg)
{
	pthread_cleanup_push(fun,NULL);
	while(1)
	{
		//上锁
		pthread_mutex_lock(&mymutex);
		num++;
		printf("生产了一件产品,目前产品数量是:%d\n",num);
		sleep(5);
		//解锁
		pthread_mutex_unlock(&mymutex);
	}
	pthread_cleanup_pop(0);
}

//销售者
void *sale(void *arg)
{
	pthread_cleanup_push(fun,NULL);
	while(1)
	{
		//上锁
		pthread_mutex_lock(&mymutex);
		num--;
		printf("销售了一件产品,目前产品数量是:%d\n",num);
		sleep(5);
		//解锁
		pthread_mutex_unlock(&mymutex);
	}
	pthread_cleanup_pop(0);
}

int main()
{
	pthread_t id1,id2;
	
	//初始化互斥锁
	pthread_mutex_init(&mymutex,NULL);
	
	//创建两个线程--》分别表示生产部门和销售部门
	pthread_create(&id1,NULL,product,NULL); //生产部门
	pthread_create(&id2,NULL,sale,NULL);    //销售部门
	
	sleep(2);
	
	//干掉销售部门
	pthread_cancel(id2);
	
	//阻塞
	pthread_join(id1,NULL);
	pthread_join(id2,NULL);
	return 0;
}

解锁完毕之后延时一丢丢防止自己给自己上锁

#include "myhead.h"

//定义一个全局变量表示目前库存数量
int num=0;

//定义一个互斥锁
pthread_mutex_t mymutex;

//用代码来模拟生产和销售

//生产者
void *product(void *arg)
{
	while(1)
	{
		//上锁
		pthread_mutex_lock(&mymutex);
		num++;
		printf("生产了一件产品,目前产品数量是:%d\n",num);
		sleep(1);
		//解锁
		pthread_mutex_unlock(&mymutex);
		//解锁完毕有两种可能性:
		//第一种:生产者解锁完毕,生产者自己立马无耻地上锁
		//第二种:销售者也有机会来抢这把锁
		//究竟是哪一种情况,取决于cpu调度
		usleep(100); //延时一丢丢,直接排除了第一种可能性,防止自己解锁自己马上上锁 
	}
}

//销售者
void *sale(void *arg)
{
	while(1)
	{
		//上锁
		pthread_mutex_lock(&mymutex);
		num--;
		printf("销售了一件产品,目前产品数量是:%d\n",num);
		sleep(1);
		//解锁
		pthread_mutex_unlock(&mymutex);
		//解锁完毕有两种可能性:
		//第一种:销售者解锁完毕,销售者自己立马无耻地上锁
		//第二种:生产者也有机会来抢这把锁
		//究竟是哪一种情况,取决于cpu调度
		usleep(100); //延时一丢丢,直接排除了第一种可能性,防止自己解锁自己马上上锁 
	}
}

int main()
{
	pthread_t id1,id2;
	
	//初始化互斥锁
	pthread_mutex_init(&mymutex,NULL);
	
	//创建两个线程--》分别表示生产部门和销售部门
	pthread_create(&id1,NULL,product,NULL); //生产部门
	//sleep(1); //北鼻手段
	pthread_create(&id2,NULL,sale,NULL);    //销售部门
	
	//阻塞
	pthread_join(id1,NULL);
	pthread_join(id2,NULL);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hqb_newfarmer

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值