关闭

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

标签: 互斥锁-mutex线程同步
243人阅读 评论(0) 收藏 举报
分类:

线程间同步一 ———— 互斥锁(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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:38648次
    • 积分:898
    • 等级:
    • 排名:千里之外
    • 原创:51篇
    • 转载:4篇
    • 译文:1篇
    • 评论:6条
    最新评论