我一直在使用 POSIX 线程创建示例并发错误的程序。
我的总体问题是 main() 线程和由pthread_create()
. 我最初的理解是它们几乎相同,但是我从下面的两个程序中得到了不同的结果。
在显示我编写的代码之前展开,我想知道的是:以下之间是否有区别。
int main() {
...
pthread_create(&t1, NULL, worker, NULL);
pthread_create(&t2, NULL, worker, NULL);
...
}
和
int main() {
...
pthread_create(&t1, NULL, worker, NULL);
worker();
...
}
使用完整的示例程序进行扩展。我已经制作了同一个程序的两个版本。它们都具有相同的功能worker()
void *worker(void *arg) {
printf("Entered worker function\n");
int myid;
int data = 999;
pthread_mutex_lock(&gidLock);
myid = gid;
gid++;
printf("myid == %d\n", myid);
pthread_mutex_unlock(&gidLock);
if (myid == 0) {
printf("Sleeping since myid == 0\n");
sleep(1);
result = data;
printf("Result updated\n");
}
return NULL;
}
gid
并且data
是全局变量,初始化为 0。
main()
以下功能有什么区别
int main_1() {
pthread_t t1, t2;
int tmp;
/* initialize globals */
gid = 0;
result = 0;
pthread_create(&t1, NULL, worker, NULL);
pthread_create(&t2, NULL, worker, NULL);
pthread_join(t2, NULL);
printf("Parent thread exited worker function\n");
tmp = result;
printf("%d\n", tmp);
pthread_exit((void *) 0);
}
和
int main_2() {
pthread_t t1;
int tmp;
/* initialize globals */
gid = 0;
result = 0;
pthread_create(&t1, NULL, worker, NULL);
worker(NULL);
printf("Parent thread exited worker function\n");
tmp = result;
printf("%d\n", tmp);
pthread_exit((void *) 0);
}
样本输出main_1()
Entered worker function
myid == 0
Sleeping since myid == 0
Entered worker function
myid == 1
Parent thread exited worker function
0
Result Updated
样本输出main_2()
Entered worker function
myid == 0
Sleeping since myid == 0
Entered worker function
myid == 1
/* program waits here */
Result updated
Parent thread exited worker function
999
编辑:该程序故意存在并发错误(违反原子性)。通过调用 sleep() 来尝试强制错误交错发生,从而增加了延迟。该程序的目的是用于测试自动检测并发错误的软件。
我认为main_1()
和main_2()
本质上是相同的程序,当在同一系统上运行时应该导致相同的交错(或基本上相同的交错;它是不确定的,但在同一系统上运行相同的程序只会探索一小部分潜在的调度并且很少偏离[1])。
“期望的”输出是来自main_1()
我不确定为什么线程myid == 1
停止并且不返回main_2()
。如果我不得不猜测
感谢您阅读本文,如果有人需要更多信息,我很乐意提供帮助。以下是完整源代码的链接。
main_1()
:https ://gist.github.com/2942372
main_2()
:https ://gist.github.com/2942375
我一直在编译gcc -pthread -lpthread
再次感谢。
[1] S. Park,S. Lu,Y. Zhou。“CTrigger:从隐藏处暴露原子性违规漏洞”