gpt4 book ai didi

c - 在 C 中类型转换 pthread 的返回值时出现意外结果

转载 作者:太空宇宙 更新时间:2023-11-04 06:56:16 24 4
gpt4 key购买 nike

我在 C 中练习 pthread,尝试制定一个函数,在线程之间尽可能平均地分配工作负载。每个线程返回一个整数,表示分配给它们的工作量。

#include <stdio.h>
#include <pthread.h>
#define THREADS 3
#define ITEMS 10

pthread_mutex_t locker = PTHREAD_MUTEX_INITIALIZER;
void* worker(void* arg){
int id = *(int*)arg;
int chunk = ITEMS/THREADS;
int start = chunk * id;
int end = id == THREADS - 1 ? ITEMS : start + chunk;
for(int i = start; i < end; i ++){
//do some work;
}
pthread_mutex_lock(&locker);
//do some work
pthread_mutex_unlock(&locker);
return end - start; //here return type should be (void *), I casted it to (int).
}

int main(void){
pthread_t ids[THREADS];
int args[THREADS];
for(int i = 0; i < THREADS; i ++){
args[i] = i;
pthread_create(ids + i,NULL,worker,&args[i]);
}

int total = 0;
int temp;
for(int i = 0; i < THREADS; i ++){
pthread_join(ids[i],&temp); //param here should be (void**), I cast it to (int*)
total = total + temp;
printf("Thread %d process %d items\n",i,temp);
}

printf("Get total items:%d\n",total);
}

我想对每个线程的返回值求和,以检查是否所有项目都已处理。因为我比较懒,只是小小练习了一下,所以我直接把每个线程的返回值从(void *)都转成了(int)。然后我得到了一些让我很困惑的输出。事实证明我可以成功地从变量“temp”中读取值,但是当我尝试这样做时

total = total + temp;

total 的值没有改变...我通过将“temp”的类型从 int 更改为 long 解决了这个问题,但我不明白为什么内存中的字节数在这里很重要。

这是一个示例输出

Thread 0 process 3 items
Thread 1 process 3 items
Thread 2 process 4 items
Get total items:4

PS:我确实知道这样做的正确方法是什么。我不明白的是,当我将整数转换为指针然后将其存储在 4 字节内存中时会发生什么?为什么可以打印出值,但计算失败?如果我使用 long(与 void* 大小相同)而不是 int(4 字节内存)那么一切正常,原因是什么?

最佳答案

如果您小心并使用 uintptr_t来自 <stdint.h>小心,你可以做你想做的,像这样:

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

#define THREADS 3
#define ITEMS 10

pthread_mutex_t locker = PTHREAD_MUTEX_INITIALIZER;

static void *worker(void *arg)
{
int id = *(int *)arg;
int chunk = ITEMS / THREADS;
int start = chunk * id;
int end = id == THREADS - 1 ? ITEMS : start + chunk;
for (int i = start; i < end; i++)
printf("A TID %d: s = %2d; e = %2d; i = %2d\n", id, start, end, i);
pthread_mutex_lock(&locker);
for (int i = start; i < end; i++)
printf("B TID %d: s = %2d; e = %2d; i = %2d\n", id, start, end, i);
pthread_mutex_unlock(&locker);
return (void *)(uintptr_t)(end - start);
}

int main(void)
{
pthread_t ids[THREADS];
int args[THREADS];
for (int i = 0; i < THREADS; i++)
{
args[i] = i;
pthread_create(ids + i, NULL, worker, &args[i]);
}

int total = 0;
int temp;
void *vp;
for (int i = 0; i < THREADS; i++)
{
pthread_join(ids[i], &vp); // param here should be (void**), I cast it to (int*)
temp = (uintptr_t)vp;
total = total + temp;
printf("Thread %d process %2d items (total = %2d)\n", i, temp, total);
}

printf("Get total items: %d\n", total);
return 0;
}

示例输出:

A TID 0: s =  0; e =  3; i =  0
A TID 1: s = 3; e = 6; i = 3
A TID 2: s = 6; e = 10; i = 6
A TID 0: s = 0; e = 3; i = 1
A TID 1: s = 3; e = 6; i = 4
A TID 2: s = 6; e = 10; i = 7
A TID 0: s = 0; e = 3; i = 2
A TID 1: s = 3; e = 6; i = 5
A TID 2: s = 6; e = 10; i = 8
B TID 0: s = 0; e = 3; i = 0
A TID 2: s = 6; e = 10; i = 9
B TID 0: s = 0; e = 3; i = 1
B TID 0: s = 0; e = 3; i = 2
B TID 1: s = 3; e = 6; i = 3
B TID 1: s = 3; e = 6; i = 4
B TID 1: s = 3; e = 6; i = 5
Thread 0 process 3 items (total = 3)
B TID 2: s = 6; e = 10; i = 6
B TID 2: s = 6; e = 10; i = 7
B TID 2: s = 6; e = 10; i = 8
B TID 2: s = 6; e = 10; i = 9
Thread 1 process 3 items (total = 6)
Thread 2 process 4 items (total = 10)
Get total items: 10

请注意,第一组输出(标记为 A )是交错的。第二组(标记为 B )由互斥体序列化。碰巧它们在此示例输出中按顺序 0、1、2 执行;这是正常的但不是保证的顺序。最后A行由线程 2 生成,而线程 0 已锁定互斥锁。父进程在线程 2 仍然忙碌时加入了线程 0。

有一次,当输出通过管道传输到日志记录程序时,我得到:

A TID 0: s =  0; e =  3; i =  0
A TID 2: s = 6; e = 10; i = 6
A TID 1: s = 3; e = 6; i = 3
A TID 0: s = 0; e = 3; i = 1
A TID 2: s = 6; e = 10; i = 7
A TID 1: s = 3; e = 6; i = 4
A TID 0: s = 0; e = 3; i = 2
A TID 2: s = 6; e = 10; i = 8
A TID 1: s = 3; e = 6; i = 5
A TID 2: s = 6; e = 10; i = 9
B TID 0: s = 0; e = 3; i = 0
B TID 0: s = 0; e = 3; i = 1
B TID 0: s = 0; e = 3; i = 2
B TID 1: s = 3; e = 6; i = 3
B TID 1: s = 3; e = 6; i = 4
B TID 1: s = 3; e = 6; i = 5
B TID 2: s = 6; e = 10; i = 6
B TID 2: s = 6; e = 10; i = 7
B TID 2: s = 6; e = 10; i = 8
B TID 2: s = 6; e = 10; i = 9
Thread 0 process 3 items (total = 3)
Thread 1 process 3 items (total = 6)
Thread 2 process 4 items (total = 10)
Get total items: 10

关于c - 在 C 中类型转换 pthread 的返回值时出现意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44092799/

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