main() 函数中的全局变量 var 的值有时会出现 -1 和
有时 1 .如何在不使用睡眠功能的情况下编写健壮的代码
以便线程有时间启动和运行。
对于那些刚接触多线程编程的人来说,一个令人痛苦的普遍误解是,像您这样的问题是时间问题。情况并非如此,至少从大多数现代高级编程语言的线程和内存模型的角度来看并非如此。仅靠延迟无法确保一个线程会看到另一个线程对内存产生的影响,因此健壮的代码不会为此目的使用诸如 sleep() 之类的计时函数。
相反,问题是同步之一。该区域包含有关一个线程写入内存的内容必须对其他线程可见的规则。它还涵盖了用于使线程能够影响其他线程的执行的特殊类型的对象和函数,通常是通过暂时阻止它们继续进行。这两个方面密切相关。
pthread_create() 和 pthread_join() 函数具有同步效果。除其他事项外,线程 T1 在调用 pthread_create() 以启动线程 T2 之前对内存的所有写入对 T2 都是可见的(对同一内存进行模后续重写)。在通过pthread_join() 成功加入 T2 后,T2 对内存的所有写入对 T1 可见。因此,对所提出问题的一种解决方案是等到加入第二个线程之后再尝试读取var,正如@Robert's answer 所建议的那样。
如果不希望这样做,那么您将需要使用某种其他类型的同步机制来使主线程等待第二个更新var。这种对同步对象的等待也会使第二个线程的写入对主线程可见。
pthreads 提供的最通用的同步技术是条件变量,它必须与互斥体一起使用。您会在 SO 和其他地方找到许多关于如何正确使用 CV 的解释。
但是,对于您的特定情况,您可能会发现信号量更易于设置和使用。信号量在技术上与 pthreads 库本身是分开的,但它们具有合适的同步语义,既可以使线程等待,也可以使一个线程的内存操作对另一个线程可见。可能看起来像这样:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
int var = -1; // GLobal Variable
sem_t semaphore;
void *myThreadFun(void *vargp)
{
var = 1;
// increment the semaphore's value
sem_post(&semaphore);
return NULL;
}
int main()
{
pthread_t thread_id;
// initialize the semaphore with value 0
sem_init(&semaphore, 0, 0);
printf("Before Thread\n");
pthread_create(&thread_id, NULL, myThreadFun, NULL);
// Wait until the semaphore's value can be decremented by one without
// it becoming negative (and then perform the decrement before proceeding).
sem_wait(&semaphore);
printf("var=%d",var);
pthread_join(thread_id, NULL);
printf("After Thread\n");
exit(0);
}