2010-03-23 67 views
4

我想多线程的应用程序,但是我使用的一个库不支持多线程(我不知道什么是正确的单词?同步?)。如果一个库不是多线程,该怎么办?

我有什么选择?

据我所知,在java中的线程和进程(Runtime.exec)之间没有任何东西(在jvm中没有抽象类似于独立的“java进程”)。

你会如何处理?

编辑

感谢所有的答案,再次,一层间接的伎俩。

+2

您正在查找的单词是“线程安全的”。 – 2010-03-23 13:38:56

+0

@Stephen C:谢谢。我无法想起它。 – LB40 2010-03-23 13:54:17

回答

11

您可以确保所讨论的库一次只能从一个线程使用。如果它包含可实例化的类,则有一种可能性是将它们保存在thread local storage中。

或者你可以在它周围建立一个线程安全的wrapper

这些方法也可以组合,例如,你可以将这个库封装到一个类中(在这种情况下,它将是一个Facade),它本身不是线程安全的,但是一次只能从一个线程访问其实例。

更新:为@Wim指出,如果库管理全局状态,你必须一个线程安全的包装,以确保改变线程之间可见。

+0

第一个确实意味着第二个。您需要内存屏障来确保缓存一致性(每个线程应该在库中的任何全局状态下具有相同的视图) – 2010-03-23 13:43:07

+0

@Wim非常好的一点,谢谢。 – 2010-03-23 13:51:08

6

我会创建一个Facade,而不是直接使用该库。门面应该将连接/呼叫同步到图书馆。

喜欢的东西:

External Call External Call External Call 
     |    |    | 
     ----------------------------------    
        Wrapper 
         | 
        Library 

更新:

的立面可能是错误的设计模式,因为它是用来隐藏功能。 包装应该作为设计模式

+3

Facade是一个稍微不同的问题的设计模式 - 它应该是一个包装或适配器。 – 2010-03-23 13:30:51

+0

Facade应该隐藏功能,在这种情况下其他类。也许你是对的,它也可能是一个包装。 – 2010-03-23 13:33:40

2

我会写一个瘦包装,所有的相关方法是同步的,并且我然后在我的代码中使用,而不是直接使用图书馆的类和方法随处可见。我首先要评估一下,图书馆的哪些部分实际上是必要的。

有时替代方案可以是为每个线程使用库对象的单独实例。但是在这种情况下,这些实例不能在线程间共享。

+0

作为同步方法的替代方法,您可以使用锁定(例如ReentrantReadWriteLock)来减少瓶颈,前提是您了解库管理器的行为并可以决定何时使用ReadLock和WriteLock。 – Sylar 2010-03-23 13:39:09

+1

@塞巴斯蒂安:如果你对图书馆有足够的了解,可以完成。也许应该指出,如果这导致多个锁对象,那么显然你也必须确保避免死锁。 – 2010-03-23 13:46:26

3

很大程度上取决于库的大小以及它的用途。首先要做的是评估你可能实际存在并发问题的地方。只是因为您在多个线程中使用库并不意味着它不能用于多个线程。在API中查找具体说明“这不是线程安全”的项目,如果您将使用API​​的那部分,则需要自己同步它。最简单的解决方案是创建一个包装类来同步所有的方法。例如,查看集合实用程序的源代码(如Collections.synchronizedList等)。

+1

请注意,尽管设计时考虑到线程安全的库并不很明确地在其API文档中明确声明“这不是线程安全的”:-( – 2010-03-23 13:48:04

2

看看Collections API中的相似问题是如何解决的。所有集合默认都不是线程安全的。

但是当你需要一个线程安全的集合,你只需用

Collections.synchronizedCollection(unsafeCollection) 

实现从用户隐藏得到它,它不是API的一部分。你可以用同样的方法。

相关问题