zoukankan      html  css  js  c++  java
  • [linux basic 基础]----同步互斥量

    互斥量,运行程序元锁住某个对象,使得每次只能有一个线程访问它;为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁它 ;
    基本函数与用于信号量的函数非常相似
    #include <pthread.h>
    int pthread_mutex_init(pthread_mutex_t *mutext, const pthread_mutexattr_t *mutexattr);
    int pthread_mutext_lock(pthread_mutex_t *mutex);
    int pthread_mutext_unlock(pthread_mutex_t *mutex);
    int pthread_mutext_destory(pthread_mutex_t *mutex);
    这些函数成功,返回0,失败返回错误代码,不会设置errno,所以必须对返回代码进行检查
    与信号量类似,这些参数都是一个先前声明过的对象的指针,对互斥量来说,这个对象类型为pthread_mutext_t。
    pthread_mutext_init函数中的属性参数与性能我们设置互斥量的属性,而属性控制着互斥量的行为;
    熟悉类型默认是fast,但他有一个缺点:如果程序试图对一个已经家了锁的互斥量调用pthread_mutex_lock,程序就会阻塞;
    但是拥有信号量的线程正是被阻塞的线程,所以互斥量就永远不会被解锁了,程序也就进入“死锁”状态;
    解决方法:就是改变互斥量的属性,让属性来检查这种情况并返回一个错误,或者让它递归操作,给同一个线程加上多个锁,但是“lock”操作和“unlock”操作必须相对应;
    ==============
    互斥量
    /*************************************************************************
        > File Name: thread4.c
        > Author: 
        > Mail: 
        > Created Time: 2016年03月27日 星期日 16时37分11秒
     ************************************************************************/
    
    #include<stdio.h>
    #include<unistd.h>
    #include<stdlib.h>
    #include<string.h>
    #include<pthread.h>
    #include<semaphore.h>
    
    void *thread_function(void *arg);
    
    //声明了互斥量,工作区,控制结束的变量
    pthread_mutex_t work_mutex; //protect both work_area and time_to_exit
    #define WORK_SIZE 1024
    char work_area[WORK_SIZE];
    int time_to_exit = 0;
    
    int main(){
        int res;
        pthread_t a_thread;
        void *thread_result;
        res = pthread_mutex_init(&work_mutex,NULL);//初始化mutex
        if(res!=0){
            perror("mutex initialization failed");
            exit(EXIT_FAILURE);
        }
        res = pthread_create(&a_thread,NULL,thread_function,NULL);
            //启动新的thread
        if(res != 0){
            perror("Thread creation failed");
            exit(EXIT_FAILURE);
        }
    
        pthread_mutex_lock(&work_mutex);//首先给工作区work_area加锁
        printf("input some text. Enter 'end' to finish
    ");
        while(!time_to_exit){
            fgets(work_area,WORK_SIZE,stdin);//读入文本
            pthread_mutex_unlock(&work_mutex);//解锁允许其他进程访问它,来统计
            while(1){
                pthread_mutex_lock(&work_mutex);//周期性加锁,
    
                if(work_area[0] != ''){//检查其他线程是否统计完毕
                    //work_area[0] = ''表示统计完毕,break出while(1)
                    //否则,解锁,等待
                    pthread_mutex_unlock(&work_mutex);
                    sleep(1);
                }else{
                    break;
                }
            }
        }
    
        pthread_mutex_unlock(&work_mutex);
        printf("
    Waiting for thread to finish...
    ");
        res = pthread_join(a_thread,&thread_result);
        if(res!=0){
            perror("Thread join failed");
            exit(EXIT_FAILURE);
        }
        printf("Thread join
    ");
        pthread_mutex_destroy(&work_mutex);
        exit(EXIT_FAILURE);
    }
    
    void *thread_function(void *arg){
        sleep(1);
        pthread_mutex_lock(&work_mutex);//新的thread启动对mutex进行加锁
          //如果mutex已经加锁,这个调用将阻塞直到他被释放为止
          //一旦获得访问权,就检查是否申请退出程序,end<>work_area[]比较
        //如果work_area[]==end那么,设置time_to_exit,work_area[0] = '',exit
    
    
        //如果没有申请退出程序,那么统计字符个数,work_area[0] = ''
        while(strncmp("end",work_area,3) != 0){
            printf("you input %d characters
    ",strlen(work_area)-1);
            work_area[0] = '';//我们利用work_area[0]==''的方式,通知输入
            //线程,本线程已经完成统计字符工作;
            pthread_mutex_unlock(&work_mutex);//解锁
            sleep(1);//等待main线程继续运行
            pthread_mutex_lock(&work_mutex);
                 //尝试加锁,如果成功,就检查是否main线程又有新的字符要处理
            while(work_area[0] == ''){
                pthread_mutex_unlock(&work_mutex);//如果没有字符要处理,解锁
                sleep(1);//等待
                pthread_mutex_lock(&work_mutex);//尝试加锁
            }
        }
    
        time_to_exit = 1;
        work_area[0] = '';
        pthread_mutex_unlock(&work_mutex);
        pthread_exit(0);
    }

    编译方式

    lizhen@lizhen:~/basic$ cc -D_REENTRANT thread4.c -o thread4 -lpthread

    运行方式

    lizhen@lizhen:~/basic$ ./thread4
    input some text. Enter 'end' to finish
    hello
    you input 5 characters
    end
    
    Waiting for thread to finish...
    Thread join
    lizhen@lizhen:~/basic$ 
  • 相关阅读:
    设计模式的原则
    List是线程安全的吗?如果不是该怎么办呢?安全的List对性能的影响有多大呢?
    StringBuilder是不是线程安全的?
    并行运算和普通运算之性能比较
    分布式与集群的区别
    sql查询性能分析
    C#代码实现,确保windows程序只有一个实例(instance)
    jQuery UI
    开源框架完美组合之Spring.NET + NHibernate + ASP.NET MVC + jQuery + easyUI 中英文双语言小型企业网站Demo
    整理的一些学习网站资料
  • 原文地址:https://www.cnblogs.com/li-daphne/p/5326079.html
Copyright © 2011-2022 走看看