以特定顺序执行pthreads?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了以特定顺序执行pthreads?相关的知识,希望对你有一定的参考价值。

我一直在尝试编写一个程序(用于学习),其中将有两个线程(AB),并且两个线程应该一个接一个地执行。例如,如果线程只显示/打印Thread AThread B,那么它们应该永远以该特定顺序打印。

期望的输出是

In Thread: thread1
In Thread: thread2
In Thread: thread1
In Thread: thread2
....

我编写的程序使用conditional variables进行同步。我已经厌倦了mutexsemaphore,但他们确实保证互相排斥,但他们不按特定顺序打印信息。我理解该问题与调度程序的线程的scheduling有关,并且刚刚释放互斥锁的线程可能会立即再次锁定它。有关更多信息,请参阅link的链接。

#include <stdio.h>

#include <ctype.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>

#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>

pthread_cond_t cond;
pthread_mutex_t mutex;

int thread1_ret = 0;
void *thread1(void *arg)
{
    while (1) {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond, &mutex);

        printf("In Thread: %s
", __func__);

        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }
    thread1_ret = 5;
    return &thread1_ret;
}

int thread2_ret = 0;
void *thread2(void *arg)
{
    pthread_mutex_lock(&mutex);
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);
    while (1) {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond, &mutex);

        printf("In Thread: %s
", __func__);

        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }
    thread2_ret = 5;
    return &thread2_ret;
}

int main(int argc, char *argv[])
{
    pthread_t t1, t2;
    pthread_attr_t attr;

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);


    pthread_cond_init(&cond, NULL);
    pthread_mutex_init(&mutex, NULL);

    pthread_create(&t1, &attr, thread1, NULL);
    pthread_create(&t2, &attr, thread2, NULL);

    pthread_attr_destroy(&attr);

    void *ret;
    pthread_join(t1, &ret);
    printf("Thread Returned: %d
", *(int *)ret);
    pthread_join(t2, &ret);
    printf("Thread Returned: %d
", *(int *)ret);

    return 0;
}

我的程序运行正常,但一段时间(2-3秒)后停止打印。我无法在我的代码中找到错误。如果有人指导我使用其他解决方案以更有效和标准的方法实现同样的事情(如果有其他标准和有效的方法来解决这样的问题陈述),那将是很好的。

答案

当没有线程在pthread_cond_waitspurious wakes-ups中等待时,条件变量通知会丢失,因此代码必须等待更改共享状态。

工作范例:

#include <stdio.h>

#include <ctype.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>

#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
unsigned state = 0;

int thread1_ret = 0;
void *thread1(void *arg)
{
    unsigned state_copy;
    pthread_mutex_lock(&mutex);
    state_copy = state;
    pthread_mutex_unlock(&mutex);

    while(1) {
        pthread_mutex_lock(&mutex);
        while(state_copy == state)
            pthread_cond_wait(&cond, &mutex);
        state_copy = ++state;

        printf("In Thread: %s
", __func__);

        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&cond);
    }
    thread1_ret = 5;
    return &thread1_ret;
}

int thread2_ret = 0;
void *thread2(void *arg)
{
    unsigned state_copy;
    pthread_mutex_lock(&mutex);
    state_copy = ++state;
    pthread_mutex_unlock(&mutex);
    pthread_cond_signal(&cond);

    while (1) {
        pthread_mutex_lock(&mutex);
        while(state_copy == state)
            pthread_cond_wait(&cond, &mutex);
        state_copy = ++state;

        printf("In Thread: %s
", __func__);

        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&cond);
    }
    thread2_ret = 5;
    return &thread2_ret;
}

int main(int argc, char *argv[])
{
    pthread_t t1, t2;
    pthread_create(&t1, NULL, thread1, NULL);
    pthread_create(&t2, NULL, thread2, NULL);

    void *ret;
    pthread_join(t1, &ret);
    printf("Thread Returned: %d
", *(int *)ret);
    pthread_join(t2, &ret);
    printf("Thread Returned: %d
", *(int *)ret);

    return 0;
}

请注意,上面的代码在释放互斥锁后发出条件变量的信号。这是微优化,但是,如果需要唤醒等待线程中的FIFO顺序,则必须在发信号时锁定互斥锁。见pthread_cond_signal

pthread_cond_broadcast()pthread_cond_signal()函数可以由线程调用,无论它当前是否拥有调用pthread_cond_wait()pthread_cond_timedwait()的线程在等待期间与条件变量相关联的互斥锁;但是,如果需要可预测的调度行为,则该互斥锁应由调用pthread_cond_broadcast()pthread_cond_signal()的线程锁定。

以上是关于以特定顺序执行pthreads?的主要内容,如果未能解决你的问题,请参考以下文章

如何使多个 Spring HandlerInterceptor 以特定顺序执行

html 将以编程方式附加外部脚本文件的javascript代码片段,并按顺序排列。用于响应式网站,其中ma

如何强制 SQL Server 以特定顺序执行查询

C代码pthread信号量程序,有3个线程按顺序打印

是否可以向特定的 pthread ID 发送信号?

互斥量和执行顺序