线程间同步一 ———— 互斥锁(mutex)

来源:互联网 发布:下载华泰证券软件 编辑:程序博客网 时间:2024/06/09 17:16

线程间同步一 ———— 互斥锁(mutex)
应用实例

/*     当主线程输入com_buf[]不为空时,子线程计算该com_buf的长度。     使用互斥锁来同步临界区,确保变量com_buf只被一个线程使用*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pthread.h>#define __DEBUG  /* Enables or disables debug output */  #ifdef __DEBUG  #define DBG(fmt, args...) fprintf(stdout, "XJTU_DBG: " fmt, ## args)  #else  #define DBG(fmt, args...)  #endif  #define ERR(fmt, args...) fprintf(stderr, "XJTU_ERR: " fmt, ## args) pthread_mutex_t mutex;/* 主线程输入,子线程计算长度 */char com_buf[255];/* 全局变量 */int time_to_exit = 0;/* 子线程-统计输入字串com_buf长度 */void *thread_fun(){    sleep(1);    /* 临界区同步 */    pthread_mutex_lock(&mutex);    while(strncmp(com_buf,"quit",4)!=0)    {        DBG("You input %d characters.\n",strlen(com_buf)-1);        com_buf[0]='\0';        pthread_mutex_unlock(&mutex);        sleep(1);        /* 周期性检查com_buf,为空不能执行统计 */        pthread_mutex_lock(&mutex);        while(com_buf[0] == '\0')        {            pthread_mutex_unlock(&mutex);            sleep(1);            pthread_mutex_lock(&mutex);        }    }    /* 程序退出标志设置 */    time_to_exit = 1;    com_buf[0] = '\0';    pthread_mutex_unlock(&mutex);    pthread_exit((void *)100);}/* 主线程 */int main(int argc, char *argv[]){    int err;    void *pthread_exit_result;    pthread_t td;    /* 互斥锁初始化 */    err = pthread_mutex_init(&mutex,NULL);    if(err < 0 )    {        ERR("pthread mutex init error!\n");        exit(-1);    }    /* 子线程创建 */    err = pthread_create(&td,NULL,thread_fun,NULL);    if(err < 0 )    {        ERR("pthread create error!\n");        exit(-1);    }    /* 临界区同步 */    pthread_mutex_lock(&mutex);    DBG("Input some text. Enter 'quit' to finish\n");    while(!time_to_exit)    {        fgets(com_buf,255,stdin);        pthread_mutex_unlock(&mutex);        while(1)        {            pthread_mutex_lock(&mutex);            if(com_buf[0] != '\0')            {                pthread_mutex_unlock(&mutex);                sleep(1);            }            else                 break;        }    }    pthread_mutex_unlock(&mutex);    DBG("Waitting for main thread to finish....\n");    err = pthread_join(td,&pthread_exit_result);    if(err<0)    {        ERR("pthread join error!\n");        exit(-1);    }    DBG("sub-pthread exit code %d.\n",(int)pthread_exit_result);    pthread_mutex_destroy(&mutex);    return 0;}

代码测试
这里写图片描述
基本界定
1.线程竞争资源最根本的源头在于临界区是个窗口,为拒绝需要在窗口内执行同步访问操作。即互斥访问。
2.原子操作:计算机科学认为一组不可分割的操作。就是说一段代码要么一气执行完不能打断,要么就一句别执行。
3.锁机制可以保证临界区的互斥,解决线程间资源访问的唯一性,通过加锁保证临界区操作的原子性,这种锁机制被叫做互斥锁。
4.临界区:就是需要同步的代码段,或者说是竞争发生的窗口区域。
代码说明
1.代码比较简单,都有注释,不明白的可以留言或mail讨论。
2.通过测试 pthread_exit((void )100);函数返回的是一个(void )指针类型,而pthread_join(td,&pthread_exit_result);中第二个参数接受的返回码是(void **)类型,所有我声明一个 void *pthread_exit_result;类型变量,这样返回的指针100就直接赋值给了指针变量pthread_exit_result,所以如大家所见打印了100.
引入的问题 —— 死锁
这是互斥引入的bug。在互斥的情况下,两个线程都在等待对方持有的互斥锁释放,而导致两个线程都不能往下执行。典型的ABBA死锁(死锁拥抱):线程1获得互斥锁A,线程2获得互斥锁B,当他们要获得另一方的互斥锁时,发现被另一个线程拥有,于是俩线程都阻塞在那里,导致死锁。一种解决方法是使用pthread_mutex_trylock,但这个不是根本解决办法,根本解决办法还是如一位大师所言,最开始的数据顶层设计和线程间逻辑关系就要清新明朗,才能避免死锁。

0 0
原创粉丝点击