Ubuntu C 中 pthread_join() 的功能

Functionality of pthread_join() in Ubuntu C

正在使用 pthread 库编写小型 C 代码。我对这段代码的要求是先存钱再取钱

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

int counter = 0;
void *increase();
void *decrease();

int balance = 500;

void *deposit(void*);
void *withdraw(void*);


int main() {

    pthread_t t_inc, t_dec;
    int dep_money = 300;
    int wd_money = 100;

    pthread_create(&t_inc, NULL, deposit, &dep_money);
    pthread_create(&t_dec, NULL, withdraw, &wd_money);

    // Wait until the thread is finished
    pthread_join(t_inc, NULL);
    pthread_join(t_dec, NULL);
    }
    return 0;
}

// Functions for thread
void *deposit(void *args) {
    int *money = (int *)args;
    balance += *money;
    printf("Deposit: New balance: %d\n", balance);
    return NULL;
}

void *withdraw(void *args) {
    int *money = (int *)args;

    if (balance < *money) {
        printf("Not enough balance\n");
    } else {
        balance -= *money;
        printf("Withdraw: New balance: %d\n", balance);
    }
    return NULL;
}

我在 2 个不同的操作系统上使用过此代码,Ubuntu 和 macOS。由于某种原因,我得到了 2 个不同的结果。

对于 macOS:

Deposit: New balance: 800

Withdraw: New balance: 700

对于Ubuntu:

Withdraw: New balance: 400

Deposit: New balance: 700

但是当我在 Ubuntu 中更改 pthread_join() 的顺序时,它按照我想要的顺序工作。

pthread_create(&t_inc, NULL, deposit, &dep_money);
pthread_join(t_inc, NULL);

pthread_create(&t_dec, NULL, withdraw, &w_money);
pthread_join(t_dec, NULL);

In conclusion, my question is why in the first code run in Ubuntu it didn't run as the first order of the pthread_join(t_inc, NULL); then the second pthread_join(t_dec, NULL); instead it runs the opposite? And I had to call pthread_join() after pthread_create() immediately for it to work in order which I don't think it's efficient since I didn't create the second thread yet.

那只是一个竞争条件。在之前调用一个线程的pthread_create 并不能保证第二个线程应由第一个之后的 OS 调度。所以打电话

pthread_create(&t_inc, NULL, deposit, &dep_money);
pthread_create(&t_dec, NULL, withdraw, &wd_money);

并不意味着您将在 运行ning withdraw() 之前调用线程 运行ning deposit()。这完全取决于 OS 他们实际安排的时间,作为一名程序员,不应该对此做出任何假设。因此结果存在差异,因为任何一个线程都可能 运行 before.

所以,回答你的问题

my question is why in the first code run in Ubuntu it didn't run as the first order of the pthread_join(t_inc, NULL); then the second pthread_join(t_dec, NULL); instead it runs the opposite?

不要对线程实际的顺序有任何期望 运行。

通话中

pthread_create(&t_inc, NULL, deposit, &dep_money);
pthread_join(t_inc, NULL);

pthread_create(&t_dec, NULL, withdraw, &w_money);
pthread_join(t_dec, NULL);

将始终有效,因为您基本上已经序列化了线程创建,并且调用 deposit() 的线程应始终在生成 运行ning withdraw() 之前完成,因此它适用于所有OSs.

编辑:

为了完整起见,正如您提到的,创建线程并立即调用 join() 并没有多大用处,因为它与仅调用函数 deposit()withdraw() 一样好按顺序,考虑到这里 deposit()withdraw() 并没有真正做太多可能使主线程停止的重要工作,阻止它继续执行其他任务。此外,您通常需要处理共享变量。例如如果您只有一个变量 amount 然后每个线程都更新了相同的值,一个增加余额而另一个减少它,那么您可能需要像 mutex/condition_variable 这样的结构来实现您想要的结果,而无需竞争条件。