简体   繁体   English

关于并行POSIX线程

[英]Regarding parallel POSIX threads

I want to create two threads, which are supposed to look like this: 我想创建两个线程,它们看起来像这样:

P1: P1:

while(1) {
    printf("1");
    printf("2");
    printf("3");
    printf("4");
}
return NULL;

P2: P2:

while(1) {
    printf("5");
    printf("6");
    printf("7");
    printf("8");
}
return NULL;

According to my knowledge of parallel threads it won't print 12345678 but a completely random variation of the numbers due to lack of synchronization. 根据我对并行线程的了解,它不会打印12345678,而是由于缺少同步而导致数字的完全随机变化。

However when I try to replicate it in real code it keeps printing 1234 a few times, then switches to 5678, prints it a few times and goes back to 1234. 然而,当我尝试在实际代码中复制它时,它会继续打印1234几次,然后切换到5678,打印几次并返回到1234。

Is my understanding of threads wrong or is my code not equivalent to the problem? 我对线程的理解是错误的还是我的代码不等同于问题?

void *print1(void *arg) {
    while(1) {
        printf("1");
        printf("2");
        printf("3");
        printf("4\n");
    }
    return NULL;
}

void *print2(void *arg) {
    while(1){
        printf("5");
        printf("6");
        printf("7");
        printf("8\n");
    }
    return NULL;
}


int main() {
    pthread_t tid1, tid2;
    pthread_create(&tid1, NULL, print1, NULL);
    pthread_create(&tid2, NULL, print2, NULL);
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    return 0;

}

You can't rely on timing assumptions when multithreading. 多线程时不能依赖时序假设。

An explanation for this question is that the sequence of printf s inside your loop take so little time to execute that can be executed inside the quantum of time given to the thread. 对这个问题的一个解释是,循环中的printf序列执行时间很短,可以在给予线程的时间量内执行。

Is my understanding of threads wrong or is my code not equivalent to the problem? 我对线程的理解是错误的还是我的代码不等同于问题?

Neither. 都不是。 Your two threads just happen to be scheduled in the expected way on your system. 您的两个线程恰好按照预期的方式安排在您的系统上。 There are many reasons for the apparent synchronisation, but it is fairly unpredictable as the OS scheduler will pause one or more threads when the system gets busy. 显而易见的同步有很多原因,但由于OS调度程序在系统繁忙时会暂停一个或多个线程,因此它是相当不可预测的。 You might try running a heavy workload across multiple threads at the same time as running your example program and see if things get confused. 您可以尝试在运行示例程序的同时跨多个线程运行繁重的工作负载,并查看是否存在问题。

This is the reason for thousands of unexpected bugs in multithreaded programs, and the reason we need mutexes, semaphores, atomic writes and sophisticated thread debugging tools like helgrind or its equivalent. 这就是多线程程序中出现数千个意外错误的原因,也是我们需要互斥锁,信号量,原子写入和复杂的线程调试工具(如helgrind或其等价物)的原因。 When dealing with thread-shared data, proving there are no deadlocks or other syncronisation issues is extraordinarily difficult thing to do. 在处理线程共享数据时,证明没有死锁或其他同步问题是非常困难的事情。

While accessing shared data inside multi threaded applications it is always very important to protect shared data. 在访问多线程应用程序内的共享数据时,保护共享数据始终非常重要。 In your case you have two threads accessing the standard output simultaneously, therefore you have a race condition wherein two threads race to acquire stdout . 在您的情况下,您有两个线程同时访问标准输出,因此您有一个竞争条件,其中两个线程竞争获取stdout Therefore I've taken the liberty to adapt you program in to a case where the standard output is protected by a mutex. 因此,我已经自由地使您的程序适应标准输出受互斥锁保护的情况。 Just before the the stdout is used we lock a mutex, the other thread will also try to lock the mutex, but both can't do that in the same time simultaneously. 在使用stdout之前我们锁定互斥锁,另一个线程也会尝试锁定互斥锁,但两者都不能同时执行此操作。 Thus the 2nd thread that tries to lock is put to sleep. 因此,尝试锁定的第二个线程将进入休眠状态。

And as others have told you it might seem that the program you originally wrote made nice outputs, that more or less coincidence, on other systems there is no way you can guarantee that and the output of the two threads can mix up. 而正如其他人告诉你的那样,你最初编写的程序看起来似乎很好,或许不太巧合,在其他系统上,你无法保证这两个线程的输出可以混淆。 ending in output like 以输出结尾

1256734
8
5671234
8

etc 等等

Now you might think that once the mutex is unlocked the other will automatically take over, but that is up to the scheduler. 现在您可能会认为,一旦互斥锁被解锁,另一个将自动接管,但这取决于调度程序。 Therefore in the example below the program might do several 1234 before outputting 5678. But it will always be either 1234 or 5678 and those outputs aren't mixed. 因此,在下面的示例中,程序可能会在输出5678之前执行几次1234.但它始终为1234或5678,并且这些输出不会混合。 If you really want to alternate the two thread you have to more sophisticated output and lookup conditional variable for example, pthread API supports those as wel. 例如,如果你真的想要替换两个线程,你需要更复杂的输出和查找条件变量,pthread API也支持这些。

#include<pthread.h>
#include<stdio.h>

void *print1(void *arg) {
    pthread_mutex_t* lock = arg;
    while(1) {
        /*now we do output from one thread while we lock the
         *mutex from the main function.*/
        pthread_mutex_lock(lock);
        printf("1");
        printf("2");
        printf("3");
        printf("4\n");
        fflush(stdout);
        /*now we must lock the lock, because otherwise
         *the other thread can't lock the mutex and if
         *we would try to lock the mutex again we would
         *create a deadlock, hower recursive locking is
         *possible, but beyond the scope of my anwer.*/
        pthread_mutex_unlock(lock);
    }
    return NULL;
}

void *print2(void *arg) {
    /*see the note in the frist thread*/
    pthread_mutex_t* lock = arg;
    while(1){
        pthread_mutex_lock(lock);
        printf("5");
        printf("6");
        printf("7");
        printf("8\n");
        fflush(stdout);
        pthread_mutex_unlock(lock);
    }
    return NULL;
}


int main() {
    pthread_t tid1, tid2;
    /*lets create a lock to protect our shared resources
     *in this case the standard output.
     */
    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
    /*make sure that the mutex is available inside the thread
     *by sending a pointer to the mutex as fourth argument to
     *phtread_create.*/
    pthread_create(&tid1, NULL, print1, &lock);
    pthread_create(&tid2, NULL, print2, &lock);
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM