我正在尝试创建一个信号量并通过使用这个简单的程序进行练习,尽管在 macos 上编译时我收到了一堆已弃用的警告。我一直在寻找并无法找到让信号量在 Macos 上工作的解决方案。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#define THREAD_NUM 4
sem_t semaphore;
void* routine(void* args) {
sem_wait(&semaphore);
sleep(1);
printf("Hello from thread %d\n", *(int*)args);
sem_post(&semaphore);
free(args);
}
int main(int argc, char *argv[]) {
pthread_t th[THREAD_NUM];
sem_init(&semaphore, 0, 1);
int i;
for (i = 0; i < THREAD_NUM; i++) {
int* a = malloc(sizeof(int));
*a = i;
if (pthread_create(&th[i], NULL, &routine, a) != 0) {
perror("Failed to create thread");
}
}
for (i = 0; i < THREAD_NUM; i++) {
if (pthread_join(th[i], NULL) != 0) {
perror("Failed to join thread");
}
}
sem_destroy(&semaphore);
return 0;
}
我期望为例程函数创建线程,其中 4 个 void* 例程()存在 4 个线程。它应该 printf("Hello from thread") 从线程 0 开始到线程 3 每秒执行一次。实际发生的情况是所有 printf 语句在 1 秒后同时输出到控制台。
输出:
Hello from thread 0
Hello from thread 1
Hello from thread 2
Hello from thread 3
编译器信息:
test.c:18:1: warning: non-void function does not return a value [-Wreturn-type]
}
^
test.c:22:5: warning: 'sem_init' is deprecated [-Wdeprecated-declarations]
sem_init(&semaphore, 0, 4);
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/semaphore.h:55:42: note: 'sem_init' has been explicitly marked deprecated here
int sem_init(sem_t *, int, unsigned int) __deprecated;
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:204:40: note: expanded from macro '__deprecated'
#define __deprecated __attribute__((__deprecated__))
^
test.c:37:5: warning: 'sem_destroy' is deprecated [-Wdeprecated-declarations]
sem_destroy(&semaphore);
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/semaphore.h:53:26: note: 'sem_destroy' has been explicitly marked deprecated here
int sem_destroy(sem_t *) __deprecated;
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:204:40: note: expanded from macro '__deprecated'
#define __deprecated __attribute__((__deprecated__))
^
3 warnings generated.
我期望为例程函数创建线程,其中 4 个 void* 例程()存在 4 个线程。它应该从线程 0 开始到线程 3 每秒打印一次(“Hello from thread”)。
我希望在任何提供符合 POSIX 的 pthreads、POSIX 信号量和
sleep()
的机器上也是如此。特别是如果您解决了第一个警告 - 例如,通过在函数末尾添加 return NULL;
routine()
。
我的期望在我的 Linux 测试机上得到了满足。然而,网络上的各个部分都有评论表明 MacOS 不支持未命名信号量,而这正是您尝试通过调用
sem_init()
来使用的。据我了解,这就是您报告的弃用警告的重要性 - 功能在那里,但(我猜)它们实际上不起作用。
如果 MacOS 的
sem_init()
确实不起作用,则调用它应该 返回错误代码。你不知道这是否发生,因为你不检查它。 始终检查函数的错误指示器,如果您实际上关心它们是否成功(在这里,您当然会这样做)。
一种不需要放弃 POSIX 接口的可能解决方法是切换到命名信号量而不是未命名信号量。这将涉及使用
sem_open()
和 sem_close()
而不是 sem_init()
和 sem_destroy()
。
实际发生的是所有 printf 语句在 1 秒后同时输出到控制台。
这听起来确实像是信号量不起作用。您的线程正在工作,因为您完全获得了输出,并且它们正在并行运行,因为它们的
sleep()
几乎同时过期。再次,检查函数调用的错误指示器(示例代码中所有库函数的返回值),因为这通常会在某些内容未按预期工作时提示您,无论是因为代码有问题还是因为数据或运行环境错误。
我现在讨厌我的 MacBook Pro m1。 我也有同样的问题。 确切的问题是当我们使用 sem_init 函数时它不起作用。 您可以打印该函数的返回号。
int ret = sem_init(&count, 1, 1);
int ter = sem_init(&write, 1, 1);
printf("%d\n", ret);
printf("%d\n", ter);
解决方案是使用windows或linux机器!