gpt4 book ai didi

c - 线程无法计数,给出错误的结果

转载 作者:行者123 更新时间:2023-12-02 08:44:01 25 4
gpt4 key购买 nike

这段代码是我写的

#include <stdio.h>      /* Input/Output */
#include <stdlib.h> /* General Utilities */
#include <pthread.h> /* POSIX Threads */
unsigned int cnt=0; /*Count variable%*/
const int NITERS=1000;
void count()
{
int i=0;
for(i=0; i<NITERS; i++)
{
cnt++;
}
pthread_exit(0);
}
int main()
{
pthread_t tid1,tid2;
/* create threads 1 and 2 */
pthread_create(&tid1,NULL,count,NULL);
pthread_create(&tid2,NULL,count,NULL);
/* Main block now waits for both threads to terminate, before it exits
If main block exits, both threads exit, even if the threads have not
finished their work */
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
if(cnt!=(unsigned)NITERS*2)
{
printf("BOOM! cnt=%d, it should be %d\n",cnt,NITERS*2);
}
else
{
printf("OK! cnt=%d\n",cnt);
}
exit(0);
}

它展示了这个结果。 Result to the code

有时它得到的 cnt 为 2000,但大多数时候它给出的结果小于 2000。您能解释一下为什么会这样吗?或者这背后的原因是什么?如何修复它。您的回答和理由肯定会有很大帮助。

最佳答案

unsigned int cnt=0; 可在线程之间共享,++ 操作不会自动增加 cnt。两个线程可能读取相同的cnt值并增加,覆盖cnt。您需要应用一些并发控制机制,例如信号量或互斥锁。


如果您使用以下命令反汇编代码(假设代码名称是thread1.c)

~$ gcc thread.c -lpthread -S  

输出的汇编代号是thread1.s

你会发现 cnt++ 在你的代码中不止是一条低级别的指令:

    movl    $0, -12(%ebp)
jmp .L2
.L3:
movl cnt, %eax
addl $1, %eax
movl %eax, cnt
addl $1, -12(%ebp)
.L2:
movl NITERS, %eax

(1) cnt 拳头移动到%eax
(2) 然后加一到%exc
(3) 将%eax移动到cnt后面

并且由于线程上下文在这一行之间切换,cnt 的相同值被多个线程读取。因此 cnt++ 不是原子的。

注意:全局变量像cnt一样是线程共享的,而像i这样的局部变量是你在count()<中声明的 是特定于线程的。


我修改了您的代码并使用信号量实现了并发控制,现在它可以正常工作了。

仅显示修改后的代码

#include <pthread.h>    /* POSIX Threads */
#include <semaphore.h>
unsigned int cnt=0; /*Count variable%*/
const int NITERS=1000;

sem_t mysem;

void count()
{
int i=0;
for(i=0; i<NITERS; i++)
{
sem_wait(&mysem);
cnt++;
sem_post(&mysem);
}
pthread_exit(0);
}
int main()
{
if ( sem_init(&mysem,0,1) ) {
perror("init");
}
// rest of your code
}

这会很好用!一些例子:

nms@NMS:~$ ./thread 
OK! cnt=2000
nms@NMS:~$ ./thread
OK! cnt=2000
nms@NMS:~$ ./thread
OK! cnt=2000

关于c - 线程无法计数,给出错误的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14004993/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com