我必须编写一个线程安全库,它使用 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可以在引发异步信号时释放信号量,但这是执行和检查此操作的最佳方法(我认为只有在exit之后该函数才是信号安全的)?在多线程应用程序中,通常最好的做法是为所有信号使用单个线程管理器:该线程应该位于库中还是可以在应用程序中启动它?

谢谢大家。

请您参考如下方法:

Linux futexes 也有同样的问题。它不能完全解决,但您可以做的是将锁定信号量的进程的 pid 写入同一共享内存区域中的某处。如果另一个进程尝试锁定信号量并且花费了太长时间(对于某些“太长”值),它会通过从共享内存中读取 pid 来找出哪个进程锁定了信号量。如果该进程不再存在,您就知道自己陷入了死锁(并且您可能应该死掉,因为库的内部数据可能处于不一致的状态)。

这仍然存在一个小竞争,因为获取锁定的进程可能会在锁定之后但在写入其 pid 之前死亡。 AFAIK 使用信号量无法避免这种情况。 (如果您有一个锁实现,其中 pid 在获取时自动写入锁变量,那么它可能会起作用,但您可能需要自己编写它。)


评论关闭
IT源码网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!