[英]Accessing to return value of a thread by another one other than creating one
當callcopypass
可以以args[2]
訪問此值時,為什么copyfilepass
返回一個指向復制的字節數的指針?
#include <unistd.h>
#include "restart.h"
void *copyfilepass(void *arg) {
int *argint;
argint = (int *)arg;
/* copyfile copies from a descriptor to another */
argint[2] = copyfile(argint[0], argint[1]);
close(argint[0]);
close(argint[1]);
return argint + 2;
}
callcopypass.c
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#define PERMS (S_IRUSR | S_IWUSR)
#define READ_FLAGS O_RDONLY
#define WRITE_FLAGS (O_WRONLY | O_CREAT | O_TRUNC)
void *copyfilepass(void *arg);
int main (int argc, char *argv[]) {
int *bytesptr;
int error;
int targs[3];
pthread_t tid;
if (argc != 3) {
fprintf(stderr, "Usage: %s fromfile tofile\n", argv[0]);
return 1;
}
if (((targs[0] = open(argv[1], READ_FLAGS)) == -1) ||
((targs[1] = open(argv[2], WRITE_FLAGS, PERMS)) == -1)) {
perror("Failed to open the files");
return 1;
}
if (error = pthread_create(&tid, NULL, copyfilepass, targs)) {
fprintf(stderr, "Failed to create thread: %s\n", strerror(error));
return 1;
}
if (error = pthread_join(tid, (void **)&bytesptr)) {
fprintf(stderr, "Failed to join thread: %s\n", strerror(error));
return 1;
}
printf("Number of bytes copied: %d\n", *bytesptr);
return 0;
}
作者回答說
如果創建線程以外的其他線程通過
copyfilepass
加入,則可以訪問通過參數復制到pthread_join
的字節數。
我什至不理解答案。 除了創建一個線程外,另一個線程如何訪問返回值(即更改值?)? 您能否舉例說明一下?
答案的症結在於,可以預見的是,您可能希望從創建它的線程之外的其他線程讀取copyfilepass
線程的結果(在這種情況下為復制的字節數)。 舉例來說,假設我們有第三個線程monitorcopy
,並且tid
是全局變量而不是局部變量。 從main方法的copyfilepass
之后生成monitorcopy
。
void* monitorcopy(void* params) {
void *result
pthread_join(tid, &result);
/* Point A: Attempt to read result */
}
假設copyfilepass
返回NULL
或無意義的值。 在點A, result
為NULL
,我們無法檢索復制的字節數,因為它存儲在main方法的targs[2]
中,這超出了范圍。
假設copyfilepass
返回argint + 2
。 result
現在是指向復制的字節數的指針,即使我們與targs
不在同一范圍內。 因此,在沒有任何內存生存期問題的情況下,我們可以按以下方式訪問復制的字節數:
void* monitorcopy(void* params) {
void *result
pthread_join(tid, &result);
int bytesCopied = *((int*) result);
}
問題不在於另一個線程想要“更改返回值”,而是另一個線程是否可以訪問輸入參數( targs
)。 通常, pthread_join
允許您從某個線程,程序中的任何位置獲取結果值,只要您具有線程ID即可。 那么使用此值返回異步操作的結果是否明智?
但是,由於許多原因,此示例的編寫不佳(作為良好的多線程實踐的示例):
只有一個函數,所有變量的范圍都通過main
擴展。 這樣寫, 每個人無論如何都可以訪問輸入參數 。 您說對了,在這種情況下不需要通過pthread_join
讀取結果是正確的。
將堆棧變量( targs
)傳遞給線程是一個壞主意 。 當函數結束時,變量將超出范圍,因此,不使程序崩潰的唯一安全方法是立即加入線程,以防止targs
超出范圍。 這意味着您沒有多線程的任何好處(除非main
在加入之前做了一些額外的工作)。 它們應該是全局的,也應該在堆上分配(一個malloc
/ free
對)。
文件在main
內部打開,但在copyfilepass
內部關閉。 責任的轉移是不必要的,盡管並不罕見。 復制文件后,我要么將文件名傳遞給函數並處理該處的打開,要么關閉線程外的句柄。
無論如何,代碼作者的觀點是,您不需要在加入線程的地方訪問輸入參數:
// removed all error checks for simplicity
int main (int argc, char *argv[]) {
pthread_t tid;
// removed all error checks for simplicity
pthread_create(&tid, NULL, copy_file, argv);
// note that this function only accepts the thread id
wait_until_copied(tid);
return 0;
}
void wait_until_copied(pthread_t tid)
{
int *bytesptr;
// no way to access input args here
pthread_join(tid, (void **)&bytesptr);
printf("Number of bytes copied: %d\n", *bytesptr);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.