zoukankan      html  css  js  c++  java
  • 关于 pthread_cond_wait 和 pthread_cond_signal , signal 无效的问题

    关于一个消费者模式,,,引起的问题..

    我在io线程里不断的把一个函数调用放到队列里

    然后ruby线程就不断的从这个队列里取出函数之争并运行.

    典型的 消费者模式.

    我曾经以为是这样...



    这是work线程

    pthread_mutex_lock(&mutex2)
    while(( invoke = get_invoke() ) != NULL){
    do_invoke(invoke);
    }
    pthread_mutex_unlock(&mutex2)
    pthread_cond_wait(&cond, &mutex);


    这里是io线程

    pthread_mutex_lock(&mutex2);
    push_invoke(invoke);
    pthread_mutex_unlock(&mutex2);
    pthread_cond_signal(&cond);// 本意是打算在这里唤醒线程

    可是会出现一个情况..就是在

    pthread_mutex_unlock(&mutex2); // 这里解锁,也就是说 上面的线程就会開始运行
    pthread_cond_signal(&cond);// 本意是打算在这里唤醒线程
    这里..在unlock的时候..非常有可能work线程已经解锁了...一旦 work 比較耗时..那么就会出现..

    先 运行 io线程的 pthread_cond_signal  然后再运行 pthread_cond_wait

    由于先pthread_cond_signal后pthread_cond_wait ..那么 pthread_cond_signal 就变得无效了

    肯定会问.为什么 不先wait 再 unlock ,..可是这样会出现 io 线程一直处于无法进入的状态...

    那么解决方法例如以下:

    就是 mutex_lock 直接使用跟cond_wait 配套的相互排斥锁..


    work thread

    pthread_mutex_lock(&mutex)
    while(( invoke = get_invoke() ) != NULL){
    do_invoke(invoke);
    }
    pthread_cond_wait(&cond, &mutex);
    pthread_mutex_unlock(&mutex)
    io thread

    pthread_mutex_lock(&mutex);
    push_invoke(invoke);
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);
    

    注意.顺序换了.然后相互排斥锁换了同一个.

    肯定会问..那假设上面的開始等待后..那以下岂不是一直进去..无法解锁?.

    但事实上是这种..

    man 了一下 pthread_cond_wait

    事实上是会先把mutex 给解锁..然后在堵塞..!!这里是重点,,

    他会把mutex给unlock..那么.就可想而知了.

    io线程解锁.再通过 signal 唤醒上面的线程  :)

    事实就是这样...多看文档...经验不代表一切...



    以下是项目代码

    pthread_mutex_t pthread_ruby_invoke_call_invoke_mutex;
    pthread_cond_t pthread_ruby_invoke_call_invoke_cond;
    
    struct fs_loop_queue* ruby_invoke_loop_que;
    
    
    void
    fs_rb_loop(const char* main_file, int pathc, const char** pathv){
        
    
        for(int i = 0 ; i < pathc ; i++){
            char path[128];
            snprintf(path, 128, " $: << '%s' ", pathv[i]);
            rb_eval_string(path);
        }
        
        
        ruby_invoke_loop_que = fs_create_loop_queue(INVOKE_LEN);
        
        
        
        pthread_mutex_init(&pthread_ruby_invoke_call_invoke_mutex, NULL);
        pthread_cond_init(&pthread_ruby_invoke_call_invoke_cond, NULL);
        
        
        int ret = 0;
        rb_load_protect(rb_str_buf_new_cstr(main_file), 0, &ret);
        if(ret != 0){
            rb_p(rb_errinfo());
        }
        
        struct fs_invoke_call_function* invoke = NULL;
        do{
        retry:
            while((invoke = fs_ruby_pop_call_invoke()) != NULL){
                invoke->func((VALUE)invoke->argv);
                fs_free(invoke->argv);
                fs_free(invoke);
            }
            pthread_mutex_lock(&pthread_ruby_invoke_call_invoke_mutex);
            
            // 过了临界点.发现有数据,就回去/// 效率 * 2 .....XDDD
            if(!fs_loop_queue_empty(ruby_invoke_loop_que)){
                pthread_mutex_unlock(&pthread_ruby_invoke_call_invoke_mutex);
                goto retry;
            }
            
            pthread_cond_wait(&pthread_ruby_invoke_call_invoke_cond,
                              &pthread_ruby_invoke_call_invoke_mutex);
            
            pthread_mutex_unlock(&pthread_ruby_invoke_call_invoke_mutex);
            
            
        }while (fs_true);
        
        
    }
    
    
    fs_bool
    fs_ruby_invoke(struct fs_invoke_call_function* invoke){
        
        pthread_mutex_lock(&pthread_ruby_invoke_call_invoke_mutex);
        fs_bool ret = fs_false;
        ret = fs_loop_queue_push(ruby_invoke_loop_que, invoke);
        if(ret){
            pthread_cond_signal(&pthread_ruby_invoke_call_invoke_cond);
        }else{
            do{
                ret = fs_loop_queue_push(ruby_invoke_loop_que, invoke);
                pthread_cond_signal(&pthread_ruby_invoke_call_invoke_cond);
                
            }while (!ret);
        }
        
        pthread_mutex_unlock(&pthread_ruby_invoke_call_invoke_mutex);
        
        return fs_true;
    }
    
    
    struct
    fs_invoke_call_function* fs_ruby_pop_call_invoke(){
        
        struct fs_invoke_call_function* func = (struct fs_invoke_call_function*)fs_loop_queue_pop(ruby_invoke_loop_que);
        
        return func;
        
        
    }
    





    pthread_mutex_unlock(&mutex2)
  • 相关阅读:
    requestWindowFeature()的应用(转载)
    Android美工坊selector选择器的使用(转载)
    Activity强制横屏竖屏
    ActivityGroup的简单用法(2)Demo展示讲解
    AndroidGUI25:定制Activity的标题栏(Titlebar)(转载)
    android背景选择器selector用法汇总
    eclipse的注释字体大小如何修改?不改变代码的字体
    QML基础——QML国际化(中文示例)
    QML基础——在C++程序中使用QML
    App for Android (4) —— Eclipse篇
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4069106.html
Copyright © 2011-2022 走看看