c - Ubuntu C 中 pthread_join() 的功能

标签 c ubuntu pthreads pthread-join

使用 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一个线程在另一个线程之前 不保证第二个线程应由操作系统在第一个线程之后调度。所以打电话

pthread_create(&t_inc, NULL, deposit, &dep_money);
pthread_create(&t_dec, NULL, withdraw, &wd_money);
并不意味着您将调用正在运行的线程 deposit()在运行 withdraw() 之前.这完全取决于操作系统何时实际安排它们,作为程序员,不应对此做出任何假设。因此,结果中的差异是因为任何一个线程都可能在之前运行过。
所以,回答你的问题

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()应始终在运行 withdraw() 之前完成产生,因此它适用于所有操作系统。
编辑:
为了完整起见,正如您提到的,创建线程并立即调用 join()并没有多大用处,因为它和调用函数 deposit() 一样好。和 withdraw()按顺序,鉴于这里 deposit()withdraw()不要真正做太多可能会停止主线程的重要工作,阻止它继续执行其他任务。此外,您通常需要处理共享变量。例如如果你只有一个变量 amount然后每个线程更新相同的值,一个添加余额,另一个减去它,那么您可能需要像 mutex 这样的结构/ condition_variable 实现您想要的结果,不受竞争条件的影响。

关于c - Ubuntu C 中 pthread_join() 的功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67248380/

相关文章:

ubuntu - X Windows 文档

c - 如何使用 pthreads 在 c 中返回数组?

c - 无限期等待的函数超时(如 listen())

c - 比 calloc 更喜欢 malloc

c - 在 C 中重新分配/调整 Lua 5.1 用户数据的大小

c++ - 有多少 mutex 和 cond 变量?

c - 在 C 中线程化 : Producer Consumer taking forever to run

c - 原始套接字编程 - 为什么 printf() 会影响数据包发送?

python - 获取 IOError : [Errno 21] Is a directory error when trying to run PyInstaller

python - Scikit-learn 教程文档位置