互斥锁和死锁

互斥锁的作用与操作

互斥锁
  互斥锁是为了解决在多线程访问共享资源时,多个线程同时对共享资源操作产生的冲突而提出的一种解决方法,在执行时,哪个线程持有互斥锁,并对共享资源进行加锁后,才能对共享资源进行操作,此时其它线程不能对共享资源进行操作。只有在持有锁的线程将锁解锁释放后,其它线程才能进行抢锁加锁操作。
  主要作用就是用来解决多线程对共享资源的竞争问题。

pthread_mutex_init互斥锁初始化

原型:
  int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
  
参数:
  mutex:互斥锁变量地址(互斥锁资源)
  attr:属性信息
  
返回:
  成功:1
  失败:errorr(错误号码)

pthread_mutex_lock上锁

原型:
  int pthread_mutex_lock(pthread_mutex_t *mutex);
  
参数:
  mutex:互斥锁变量地址(互斥锁资源)

返回:
  成功:1
  失败:errorr(错误号码)

pthread_mutex_unlock解锁

原型:
  int pthread_mutex_unlock(pthread_mutex_t *mutex);
  
参数:
  mutex:互斥锁变量地址(互斥锁资源)
  
返回:
  成功:1
  失败:errorr(错误号码)

pthread_mutex_destroy销毁互斥锁

原型:
  int pthread_mutex_unlock(pthread_mutex_t *mutex);
  
参数:
  mutex:互斥锁变量地址(互斥锁资源)
  
返回:
  成功:1
  失败:errorr(错误号码)

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

pthread_mutex_t  mutex;     //定义一个锁资源变量(传参容易出问题) 

void *func(void *arg);
 
int main(int argc, char **argv)
{
    int status = pthread_mutex_init(&mutex,NULL);   //初始化互斥锁

    pthread_t thread;
    pthread_create (&thread, NULL,func,NULL);//创建线程

    while(1)       //循环上锁
    {
        int i = 0;
        pthread_mutex_lock(&mutex);//上锁
        printf("11111我上锁了\n");  
        while(1)
        {
            i++; 
            if(i == 200)
            {

                printf("i = %d\n",i);
                printf("11111我解锁了\n");  

                pthread_mutex_unlock(&mutex);   //解锁
                break;   
            }
        }
        sleep(1); //防止解锁完后立即上锁 

      
    }

    return 0;
}


void *func(void *arg)
{
    pthread_t id = pthread_self();  //获取当前线程id
	pthread_detach(id);     //设置自我分离
	
    while(1)       //循环上锁
    {
        int k = 0;
        pthread_mutex_lock(&mutex);//上锁
        printf("22222我上锁了\n");  
        while(1)
        {
            k++; 
            if(k == 200)
            {
                printf("k = %d\n",k);
                printf("22222我解锁了\n");  

                pthread_mutex_unlock(&mutex);   //解锁
                break;
                    
            }
        }
        sleep(1);   
      
    }
} 

死锁

产生死锁的原因
  当进程需要以独占的方式访问资源时,可能会发生死锁(Deadlock)。死锁是指两个或以上进程因竞争临界资源而造成的一种僵局,即一个进程等待一个已经被占用且永不释放的资源。若无外力作用,这些进程都无法向前推进。

产生死锁的四个条件

互斥条件
 涉及的资源是非共享的,即一次只能有一个进程使用。如果有另一个进程申请该资源,那么申请进程必须等待,直到该资源被释放。

不剥夺条件(非抢占)
 进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自行释放。

占有并等待(部分分配)
 进程每次申请它所需要的一部分资源。在等待一新资源的同时,进程继续占用已分配到的资源。

环路条件(循环等待)
 存在一种进程收尾相接的循环链,链中每个进程都在等待下一个进程所持有的资源,造成这组进程处于永远等待状态。

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立。反之,上述条件只要有一个不满足,就不会发生死锁。所以要避免发生死锁,只需要破坏其必要条件。

线程中防止死锁

pthread_cleanup_push压栈线程处理函数

原型:
  void pthread_cleanup_push(void (*routine)(void *), void *arg)
  
功能
 函数压栈(线程清理函数)
  
参数:
  routine:线程的取消处理函数
  arg:线程的取消处理函数的参数

pthread_cleanup_pop压栈线程处理函数

原型:
  void pthread_cleanup_pop(int execute)
  
功能
  该函数在程序异常终止时会调用pthread_cleanup_push()时压入清理函数栈,采用先入后出的栈结构管理
  
参数:
  execute:
    写0:弹栈线程的取消处理函数,但不执行该函数
    非0:弹栈线程的取消处理函数,并执行该函数
    这个参数并不影响异常终止时清理函数的执行

示例代码



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

//定义互斥锁
pthread_mutex_t  mutex;

void *routine(void *arg);

void function(void *arg);

int main()
{

	pthread_mutex_init(&mutex, NULL);//初始化互斥锁
		
	pthread_t id;//定义一个线程ID号
	pthread_create(&id, NULL, routine, NULL);//创建线程 ---》线程id号保存地址
	
	while(1)    //循环上锁
	{
		pthread_mutex_lock(&mutex); //上锁
        printf("1 我上锁啦!!\n");

        char buf[128];
		while(1)
        {
            printf("线程1:");
            scanf("%s", buf);
            if(!strcmp(buf,"A"))
            {
                break;
            }

        }

        printf("1 我解锁啦!!\n");
		pthread_mutex_unlock(&mutex);//解锁
        sleep(1);
	}
	
	pthread_mutex_destroy(&mutex);//销毁互斥锁

	pthread_exit(NULL);
}

//线程函数
void *routine(void *arg)
{
    
	pthread_t id = pthread_self();

	while(1)
	{
		
		pthread_mutex_lock(&mutex);//上锁
        pthread_cleanup_push(function,NULL);    //函数压栈(线程清理函数)

        printf("2 我上锁啦!!\n");

        char buf[128];
		while(1)
        {
            printf("线程2:");
            scanf("%s", buf);
            if(!strcmp(buf,"B"))
            {
                break;
            }
            if(!strcmp(buf,"Z"))
            {
                pthread_cancel(id);     //取消线程
            }
        }

        printf("2 我解锁啦!!\n");
        pthread_mutex_unlock(&mutex); //解锁
        pthread_cleanup_pop(0);     //正常退出不执行线程清理函数

        sleep(1);
	}

	return NULL;
}

//清理函数(防止死锁)
void function(void *arg)
{
    printf("哟,咋了\n");

    //解锁(防止线程异常结束尔造成的死锁)
    pthread_mutex_unlock(&mutex);

}

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值