2016-02-26 89 views
2

我能想到的两种方法是线程安全的库可用于:使用线程安全库

一方是由一个互斥保护的图书馆,这是由主线程初始化和使用的全局实例通过工作线程,就像这样:

mutex g_lib_mutex; 
lib_t g_lib; 

thread: 
    lock(&g_lib_mutex); 
    /* use lib */ 
    unlock(&g_lib_mutex); 


main: 
    lib_init(&g_lib); 
    start_threads(thread); 

    lock(&g_lib_mutex); 
    /* use lib */ 
    unlock(&g_lib_mutex); 

    join_threads(); 
    lib_close(&g_lib); 

其他的,是每个线程有库的本地实例,这样的事情:

thread: 
    lib_t g_lib; 
    lib_init(&g_lib); 
    /* use lib */ 
    lib_close(&g_lib); 


main: 
    start_threads(thread); 
    lib_t g_lib; 
    lib_init(&g_lib); 
    /* use lib */ 
    lib_close(&g_lib); 

以下哪种方式更正确/ p可借鉴?

在这两种情况下,我是否需要使用全局互斥锁来保护库调用?

我试图在多线程应用程序中使用libmysql和POSIX消息队列,当这个问题跨过我的脑海。

+2

您是否需要/想要跨线程共享实例? – JimmyB

+0

相关:http://stackoverflow.com/questions/11313686/using-libmysqlclient-in-multi-threaded-application – JimmyB

+0

@HannoBinder ...我不确定,但在诸如libmysql的情况下,并非所有的调用都是线程安全,看起来像我可能需要。 – Zaxter

回答

2

通常,只需初始化一次库。请记住,所有线程都发生在同一进程的内存空间中,因此无论您对线程X中的任何全局变量所做的操作对于所有线程都是如此。每个进程只能进行一次库初始化。

现在,无论库调用是线程安全还是必须受互斥锁保护,都是库的问题。现代图书馆应该有关于你允许从多个线程调用哪些函数的明确文档。如果这些信息被丢失,你可以

  • 假设改变了一些库涉及,或调用到库,用一个单一的全球互斥最差,封装的一切,或
  • 阅读的源代码图书馆找出可能出错的地方,相应地引入安全措施(互斥体/条件),并确保没有人使用该库的不同版本(可能会有所不同),或者改进文档,将该补丁发送给上游开发人员,要求他们验证您在线程安全中记录的内容是否有意并符合实际情况(文档补丁是针对任何p我知道,总是欢迎的项目)或
  • 修改库本身是线程安全的(使自己成为英雄)。
+0

谢谢你的深刻解答@Marcus。 但是线程安全库不应该有一个全局可变状态吗?所以不止一次初始化不应该是一个问题? – Zaxter

+0

不,这不是真的,@Zaxter。 “线程安全”可能意味着可以从不同线程调用一些(或全部)函数,但是库初始化通常不能是其中的一种。 –

+0

Aaahhh!这不是我第一次(错误地)推定某事......感谢您的澄清。 – Zaxter