在 C 中调用 "thread entry point" 函数作为 "normal" 函数是一种糟糕的代码习惯吗?
Is calling a "thread entry point" function, in C, as "normal" function, a bad code practice?
我最近遇到了一个非常特殊的情况,我不得不考虑在 "normal" 函数调用和 "thread entry point" 函数中使用相同的函数,使用 POSIX 线程, 在 C.
让我更好地解释一下情况:我有一个程序,根据用户的选择,它应该执行不同的任务。
两项任务非常相似,但它们的不同之处在于,在一种情况下,一组操作应与另一组操作并行执行,而在第二种情况下,几乎相同的一组操作应该必须在另一个之前执行,无需创建专用线程。
由于"common"组操作在这两种情况下非常相似,所以我实际上写了如下代码:
if(task_type==0) {
// Create two threads
pthread_create(&tid[0],NULL,&common_operations,(void *) &args);
pthread_create(&tid[1],NULL,¶llel_operations,(void *) &args);
pthread_join(tid[0],NULL);
pthread_join(tid[1],NULL);
} else if(task_type==1) {
common_operations(&args); // Thread entry point function called as "normal function"
sequential_operations(&args); // Different with respect to "parallel_operations"
}
将 "common_operations" 函数定义为:
static void *common_operations (void *arg) {
// Properly casting void *arg to the right struct, containing, among the other things, "task_type"
// Function body....
if(arg->task_type==0) {
pthread_exit(NULL);
} else {
return NULL;
}
}
我从未见过以这种方式使用的线程入口点函数,我想知道这是否可以被认为是可以接受的,或者以这种方式混合使用是否是一种糟糕的代码实践。
此外,对于这个具体案例有更好的解决方案吗?
像调用任何其他函数一样调用 "thread function" 当然是有效的。只要将(转换)为正确的类型,就没有问题,应该没问题。
它是否是好的做法是主观的。这是一个非常罕见的,很难找到任何人直接称呼它 "a bad practice, you must avoid" :)
但是,您可以稍微重写,以便 "normal" 函数与线程函数的区别很清楚。并使其成为 void
函数,这样它就不会 return 单线程调用中的任何东西,否则看起来有点奇怪。这也可以避免潜在的意大利面条代码。
/* Use it in direct, single-threaded call */
static void common_operations(common_arg_type *arg) {
// Function body....
}
/* Use it in pthread_create call */
static void *common_operations_thread(void *arg) {
common_operations(args);
return NULL; /* equivalent to pthread_exit(NULL); */
}
IMO,对于任何多线程程序,您应该考虑的因素都是一样的:函数保持线程安全,并且您从线程函数调用的任何函数也是线程安全的,等等。否则就没什么好担心的了。
我最近遇到了一个非常特殊的情况,我不得不考虑在 "normal" 函数调用和 "thread entry point" 函数中使用相同的函数,使用 POSIX 线程, 在 C.
让我更好地解释一下情况:我有一个程序,根据用户的选择,它应该执行不同的任务。
两项任务非常相似,但它们的不同之处在于,在一种情况下,一组操作应与另一组操作并行执行,而在第二种情况下,几乎相同的一组操作应该必须在另一个之前执行,无需创建专用线程。
由于"common"组操作在这两种情况下非常相似,所以我实际上写了如下代码:
if(task_type==0) {
// Create two threads
pthread_create(&tid[0],NULL,&common_operations,(void *) &args);
pthread_create(&tid[1],NULL,¶llel_operations,(void *) &args);
pthread_join(tid[0],NULL);
pthread_join(tid[1],NULL);
} else if(task_type==1) {
common_operations(&args); // Thread entry point function called as "normal function"
sequential_operations(&args); // Different with respect to "parallel_operations"
}
将 "common_operations" 函数定义为:
static void *common_operations (void *arg) {
// Properly casting void *arg to the right struct, containing, among the other things, "task_type"
// Function body....
if(arg->task_type==0) {
pthread_exit(NULL);
} else {
return NULL;
}
}
我从未见过以这种方式使用的线程入口点函数,我想知道这是否可以被认为是可以接受的,或者以这种方式混合使用是否是一种糟糕的代码实践。
此外,对于这个具体案例有更好的解决方案吗?
像调用任何其他函数一样调用 "thread function" 当然是有效的。只要将(转换)为正确的类型,就没有问题,应该没问题。 它是否是好的做法是主观的。这是一个非常罕见的,很难找到任何人直接称呼它 "a bad practice, you must avoid" :)
但是,您可以稍微重写,以便 "normal" 函数与线程函数的区别很清楚。并使其成为 void
函数,这样它就不会 return 单线程调用中的任何东西,否则看起来有点奇怪。这也可以避免潜在的意大利面条代码。
/* Use it in direct, single-threaded call */
static void common_operations(common_arg_type *arg) {
// Function body....
}
/* Use it in pthread_create call */
static void *common_operations_thread(void *arg) {
common_operations(args);
return NULL; /* equivalent to pthread_exit(NULL); */
}
IMO,对于任何多线程程序,您应该考虑的因素都是一样的:函数保持线程安全,并且您从线程函数调用的任何函数也是线程安全的,等等。否则就没什么好担心的了。