• linux c编程:线程互斥二 线程死锁


    死锁就是不同的程序在运行时因为某种原因发生了阻塞,进而导致程序不能正常运行。阻塞程序的原因通常都是由于程序没有正确使用临界资源。

    我们举个日常生活中的例子来比喻死锁。我们把马路上行驶的汽车比作运行着的程序,把马路比作临界资源,如果有两辆汽车相互碰撞,就会把车停在马路上,这样的话他们一直占用着马路这个临界资源。其它的汽车不能正常通过马路,于是整条路上的汽车都无法在马路上正常行驶,马路也被汽车堵的水泄不通。整个交通都瘫痪了,这就是“死锁”。造成死锁的原因就是发生车祸的汽车占用了马路这种临界资源,以至于其它汽车无法在马路上正常行驶。

    在实际的程序中造成死锁的原因有两种:

    1 同一个线程对已经加锁的互斥量再次加锁;

    2 线程A对互斥量一加锁,同时等待互斥量二被解锁;而此时,线程B对互斥量二加锁,同时等待互斥量一被解锁;

    首先来看第一种现象:

    int value=0;

    pthread_mutex_t mutex_value_tmp1=PTHREAD_MUTEX_INITIALIZER;

    void read_data(){

        printf("data=%d ",value);

        printf("end reading data ");

    }

    void threading_func1(){

        int i=0;

        int res=0;

        pthread_t thread_id;

        thread_id=pthread_self();

        printf("Thread id :%d ",thread_id);

        while(i<4){

            res=pthread_mutex_lock(&mutex_value_tmp1);  #第一次加锁

            if (res !=0){

                printf("thread mutex failed ");

            }

            read_data();

            res=pthread_mutex_lock(&mutex_value_tmp1);  #第二次加锁

            if (res !=0){

                printf("thread mutex failed ");

            }

            res=pthread_mutex_unlock(&mutex_value_tmp1);  #释放锁;

            printf("res=%d ",res);

            if (res !=0){

                printf("mutex unlock failed ");

            }

            Sleep(2000);

        }

        pthread_exit((void *)2);

    }

    结果执行如下:

    当线程2再次执行的时候,由于无法获取锁,因此发生死锁

    这种情况下为了避免阻塞。需要用到pthread_mutex_tryloc。

    函数pthread_mutex_trylock是pthread_mutex_lock的非阻塞版本。如果mutex参数所指定的互斥锁已经被锁定的话,调用pthread_mutex_trylock函数不会阻塞当前线程,而是立即返回一个值来描述互斥锁的状况。将上面代码中的pthread_mutex_lock全部替换为pthread_mutex_trylock。在来看下运行结果:

    每当重复加锁的时候都会发生加锁失败,但是不会发生死锁。

    下面来看下第二种情况:

    代码如下:

    int value=0;

    pthread_mutex_t mutex_value_tmp1=PTHREAD_MUTEX_INITIALIZER;

    pthread_mutex_t mutex_value_tmp2=PTHREAD_MUTEX_INITIALIZER;

    void read_data(){

        printf("data=%d ",value);

        printf("end reading data ");

    }

    void write_data(){

        value+=1;

        printf("data=%d ",value);

        printf("end writing data ");

    }

    void threading_func1(){

        int i=0;

        int res=0;

        pthread_t thread_id;

        thread_id=pthread_self();

        printf("Thread id :%d ",thread_id);

        while(i++<4){

            res=pthread_mutex_trylock(&mutex_value_tmp1);

            if (res !=0){

                printf("thread mutex1 failed ");

            }

            read_data();

            res=pthread_mutex_trylock(&mutex_value_tmp2);

            if (res !=0){

                printf("thread mutex2 failed ");

            }

            res=pthread_mutex_unlock(&mutex_value_tmp2);

            if (res !=0){

                printf("mutex2 unlock failed ");

            }

            res=pthread_mutex_unlock(&mutex_value_tmp1);

            if (res !=0){

                printf("mutex1 unlock failed ");

            }

            Sleep(2000);

        }

        pthread_exit((void *)2);

    }

    void threading_func2(){

        int i=0;

        int res=0;

        pthread_t thread_id;

        thread_id=pthread_self();

        printf("Thread id :%d ",thread_id);

        while(i++<4){

            res=pthread_mutex_lock(&mutex_value_tmp2);

            if (res !=0){

                printf("thread mutex2 failed ");

            }

            write_data();

            res=pthread_mutex_lock(&mutex_value_tmp1);

            if (res !=0){

                printf("thread mutex1 failed ");

            }

            res=pthread_mutex_unlock(&mutex_value_tmp1);

            if (res !=0){

                printf("mutex1 unlock failed ");

            }

            res=pthread_mutex_unlock(&mutex_value_tmp2);

            if (res !=0){

                printf("mutex2 unlock failed ");

            }

            Sleep(2000);

        }

        pthread_exit((void *)2);

    }

    int main()

    {

        pthread_t tid1,tid2;

        int res;

        void *tret;

        pthread_mutex_init(&mutex_value_tmp1,NULL);

        pthread_mutex_init(&mutex_value_tmp2,NULL);

        pthread_create(&tid1,NULL,threading_func1,NULL);

        pthread_create(&tid2,NULL,threading_func2,NULL);

        pthread_join(tid1,&tret);

        printf("thread 1 exit code %ld ",(long)tret);

        pthread_join(tid2,&tret);

        printf("thread 2 exit code %ld ",(long)tret);

        res=pthread_mutex_destroy(&mutex_value_tmp1);

        if (res!=0){

            printf("mutex can't be destroyed");

        }

        return 0;

    }

    运行结果如下:从下面的程序运行结果中可以看到,线程1锁住了互斥量一,同时等待互斥量二;而线程2锁住了互斥量二,同时等待互斥量一。这样便造成了死锁,进而引起了程序运行错误。在写代码的时候应该避免这类用法

  • 相关阅读:
    python PIL实现图片合成
    pycharm在windows中如何安装dlib?
    Git将文件上传至Github过程
    安装skimage和cv2
    ubuntu下pip的安装,更新及卸载
    pycharm专业版激活破解(亲测有效)
    docker部署tensorflow serving以及模型替换
    Keras在MNIST实现LeNet-5模型训练时的错误?
    Ubuntu中VMware tools的安装步骤
    win10执行Tensorflow,总是会报错“DLL load failed: 找不到指定的模块”的解决方式----终极版方式
  • 原文地址:https://www.cnblogs.com/zhanghongfeng/p/9312152.html
Copyright © 2020-2023  润新知