gpt4 book ai didi

multithreading - 通过 pthread_cond_broadcast 触发多个 pthread

转载 作者:行者123 更新时间:2023-12-03 13:18:59 35 4
gpt4 key购买 nike

由于 pthread_cond_broadcast 的 pthread 示例唤醒是稀疏的,我写了一个,但不确定这是否正确同步以及如何做到这一点:

  • 所有线程是否共享相同的 c 和 mtx 变量?
  • 是否需要 pthread_cond_wait返回测试是否确实满足某些条件?在我的情况下,每个广播调用都应该唤醒每个线程一次,但没有其他人应该这样做。 (我会防止虚假唤醒吗?)
  • 尽管异步取消类型,该程序当前不会退出。尽管 pthread_cond_wait 在示例代码中尝试延迟取消也没有成功作为取消点so .

  • 总体而言,它是否像我期望的那样工作。
     #include <pthread.h> 
    #include <iostream>
    #include <unistd.h>

    struct p_args{
    int who;
    };

    pthread_cond_t c; //share between compilation units
    pthread_mutex_t mtx;

    void *threadFunc(void *vargs){
    //pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
    struct p_args * args = (struct p_args *) vargs;

    while(true){
    //wait for trigger one loop
    pthread_mutex_lock(&mtx);
    pthread_cond_wait(&c, &mtx);
    pthread_mutex_unlock(&mtx);
    //should be entangled output showing concurrent execution
    std::cout << "t " << args->who << std::endl;

    /* expensive work */
    }
    delete args;
    }

    int main(int argc, char* argv[])
    {
    pthread_cond_init(&c, NULL);
    pthread_mutex_init(&mtx, NULL);

    pthread_t thread_id[2];

    struct p_args *args0 = new p_args();
    struct p_args *args1 = new p_args();
    args0->who = 0;
    args1->who = 1;

    pthread_create(&thread_id[0], NULL, threadFunc, args0);
    pthread_create(&thread_id[1], NULL, threadFunc, args1);

    sleep(3);
    pthread_mutex_lock(&mtx);
    pthread_cond_broadcast(&c);
    pthread_mutex_unlock(&mtx);
    sleep(3);//test if thread waits
    pthread_cancel(thread_id[0]);
    pthread_cancel(thread_id[1]);

    pthread_join (thread_id[0], NULL);
    pthread_join (thread_id[1], NULL);
    //could perform cleanup here
    return 0;
    }

    Regarding exiting deferred:
    thread_id[0] exits fine and i am stuck in line `pthread_join (thread_id[1], NULL);`, it says (Exiting) but seems stuck on a lock, with debugger:
    <br>
    [![enter image description here][2]][2]
    <br>

    编辑 我想出的最终解决方案:
    #include <pthread.h>
    #include <iostream>
    #include <unistd.h>

    struct p_args{
    int who;
    };

    pthread_cond_t c;
    pthread_mutex_t mtx;
    bool doSome[2];
    bool exitFlag;

    void *threadFunc(void *vargs){
    struct p_args * args = (struct p_args *) vargs;

    while(true){
    //wait for trigger one loop
    pthread_mutex_lock(&mtx);
    do {
    pthread_cond_wait(&c, &mtx);
    if(exitFlag) {
    std::cout << "return " << args->who << std::endl;
    delete args;
    pthread_mutex_unlock(&mtx);
    return NULL;
    }
    } while(doSome == false);
    doSome[args->who] = false;
    pthread_mutex_unlock(&mtx);
    std::cout << "t " << args->who << std::endl;
    }
    }

    int main(int argc, char* argv[])
    {
    pthread_cond_init(&c, NULL);
    pthread_mutex_init(&mtx, NULL);
    pthread_t thread_id[2];

    struct p_args *args0 = new p_args();
    struct p_args *args1 = new p_args();
    args0->who = 0;
    args1->who = 1;

    doSome[0] = doSome[1] = true;
    exitFlag = false;
    pthread_create(&thread_id[0], NULL, threadFunc, args0);
    pthread_create(&thread_id[1], NULL, threadFunc, args1);

    doSome[0] = doSome[1] = true;
    pthread_cond_broadcast(&c);
    sleep(3);
    doSome[0] = doSome[1] = true;
    pthread_cond_broadcast(&c);
    sleep(3);
    exitFlag = true;
    pthread_cond_broadcast(&c);

    pthread_join (thread_id[0], NULL);
    pthread_join (thread_id[1], NULL);

    return 0;
    }

    最佳答案

    1. do all threads share the same c and mtx variable?


    是的,就像任何其他全局变量一样。您可以从每个线程打印他们的地址以确认它。

    1. is it necessary upon pthread_cond_wait return to test if some condition is actually met?


    是的,所有等待接口(interface)都受到虚假唤醒的影响,您始终负责检查自己的谓词。见 documentation或一本好书。

    1. the program currently does not exit ...

    pthread_cancel都是可怕的,永远不应该使用。真的很难做对。如果您想告诉您的线程退出,请编写一个通知机制 - 将其构建到现有的谓词循环中 - 并发出信号/广播以确保所有线程都唤醒并意识到是时候死了。

    Regarding exiting deferred: thread_id[0] exits fine and i am stuck in line pthread_join (thread_id[1], NULL);, it says (Exiting) but seems stuck on a lock



    关于 pthread_cancel 的困难之一是清理。如果在您持有锁时发生取消,您需要使用 pthread_cleanup_push模拟取消兼容的 RAII 语义。否则,第一个线程可能(在这种情况下确实)在互斥锁仍被锁定的情况下死亡。

    在这种情况下,第二个线程试图从 pthread_const_wait 退出。由于取消,但它需要重新获得锁定并且不能。

    条件变量循环的通常形式是这样的(一本好的引用书应该显示类似的内容):
    void *thread(void *data)
    {
    struct Args *args = (struct Args *)data;

    /* this lock protects both the exit and work predicates.
    * It should probably be part of your argument struct,
    * globals are not recommended.
    * Error handling omitted for brevity,
    * but you should really check the return values.
    */
    pthread_mutex_lock(&args->mutex);

    while (!exit_predicate(args)) {
    while (!work_predicate(args)) {
    /* check the return value here too */
    pthread_cond_wait(&args->condition, &args->mutex);
    }
    /* work_predicate() is true and we have the lock */
    do_work(args);
    }

    /* unlock (explicitly) only once.
    * If you need to cope with cancellation, you do need
    * pthread_cleanup_push/pop instead.
    */
    pthread_mutex_unlock(&args->mutex);

    return data;
    }

    您的自定义代码可以进入 bool exit_predicate(struct Args*) , bool work_predicate(struct Args*)void do_work(struct Args*) .循环结构本身很少需要改变。

    关于multithreading - 通过 pthread_cond_broadcast 触发多个 pthread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51019730/

    35 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com