代码之家  ›  专栏  ›  技术社区  ›  vy32

等待几个线程中的一个完成?

  •  1
  • vy32  · 技术社区  · 14 年前

    我正在实现一个线程池。每个线程所需的工作是1-10秒的CPU,所以我很高兴有一个传统的线程池和工作线程,或者我很高兴为每个工作单元生成一个新线程。没关系。

    我想让主控制线程知道N个工作线程中的一个何时完成其工作并准备好进行更多的工作(或是启动另一个工作线程的时间)。我看过pthread_join和pthread_cond_wait。似乎没有办法等待N中的一个,所以我想让主线程有一个变量,它用来睡觉,让工作线程唤醒它。如果工人们不死的话,这似乎行得通。但是,如果他们死了,在工人唤醒控制器的时间和它死的时间之间有一个窗口,我不想处理。

    我看过英特尔的TBB,但它看起来比我需要的复杂得多。

    PTHREADS中是否有一个简单的等价于微软Windows中的WaitForMultipleObjects?

    3 回复  |  直到 14 年前
        1
  •  3
  •   paxdiablo    14 年前

    这是条件变量的一个相当简单的用例。

    具有活动工作项的整数计数,受互斥保护。另外,有两个条件变量,一个用于向队列上可用的工作线程发送信号,另一个用于向主线程发送线程已完成的信号。类似于:

    main:
        set freethreads to numthreads
        init mutex M, condvars TOMAIN and TOWORKER
        start N worker threads
        while true:
            wait for work item
            claim M
            while freethreads == 0:
                cond-wait TOMAIN, M
            put work item in queue
            decrement freethreads
            cond-signal TOWORKER
            release M
    
    worker:
        init
        while true:
            claim M
            while no work in queue:
                cond-wait TOWORKER, M
            get work to local storage
            release M
            do work
            claim M
            increment freethreads
            cond-signal TOMAIN
            release M
    

    注意,循环永远运行。实际上,会有信号使它们退出并运行终止/清理代码。

        2
  •  1
  •   lijie    14 年前

    你考虑过使用计数信号量吗?

        3
  •  1
  •   William X    14 年前

    从架构的角度来看,这将是线程池的责任。工人和游泳池之间的同步应该存在。

    pthread_mutex_lock()或计数信号量(sem_wait()和sem_post())对于这种同步很好。一种方法可以说明为:

    1. pool init是通过调用:sem_init(p_to_sem_t,0,int n)计算的信号量;
    2. n个工作进程通过调用:sem_wait()获取信号量;
    3. 池通过调用:sem_wait(),等待工人返回;
    4. 池检查信号量计数,以查看是否所有工人都已停驻。
    5. 工作人员在退出时释放锁:SimIn POST();