我要编写一个线程安全库,它使用POSIX信号量(用作初始值为1的互斥锁)进行同步。我发现了一些正确管理异步信号的问题。我有一个应用程序链接到这个静态库和应用程序(多线程)调用库的函数。访问一些内部结构由posix信号量控制(它是库的内部):
void library_func1(lib_handler *h)
{
sem_wait(sem);
/* do some stuff with global data */
sem_post(sem);
}
void library_func2(lib_handler *h)
{
sem_wait(sem);
/* do some stuff with global data */
sem_post(sem);
}
void library_close(lib_handler *h)
{
...
}
当一个线程锁定信号量时,如果异步信号(假设为SIGINT
)被引发,会附加什么?如果我重新启动应用程序,我将遇到死锁,因为信号量存在且值为0
。有一个函数library_close
可以在异步信号被提升时释放信号量,但这是最好的方法和检查(我认为只有在{{1}之后,该函数才是信号安全的})?在多线程应用程序中,通常一个好的做法是为所有信号都有一个单独的线程管理器:这个线程应该在库中,还是可以在应用程序中启动它?
谢谢大家。
答案 0 :(得分:0)
Linux futexes遇到了同样的问题。它不是完全可以解决的,但你可以做的是编写将信号量锁定在同一共享内存区域中某处的进程的pid。如果另一个进程试图锁定信号量并且它花费的时间太长(某些值为“太长”),它会通过从共享内存中读取pid来找出锁定信号量的进程。如果该进程不再存在,您就知道自己处于死锁状态(因为库的内部数据可能处于不一致状态,您可能应该死掉)。
由于采取锁定的过程可能在锁定之后但在编写其pid之前死亡,因此仍然存在一个小的竞争。 AFAIK使用信号量无法避免这种情况。 (如果你有一个锁实现,其中pid以原子方式写在aquire上,可能会有效,但你可能需要自己写这个。)
答案 1 :(得分:-1)
静态库的状态不会在应用程序的不同运行之间延续,并且不会被使用它的其他应用程序共享。它是使用它的应用程序状态的一部分。所以你的信号量不会处于不稳定的状态。