2010-03-23 6 views
4

Je voudrais multi-thread une application, mais une bibliothèque que j'utilise n'est pas multi-thread (je ne sais pas quel est le mot correct? Synchronisé?).Que faire si une bibliothèque n'est pas multithread?

Quelles sont mes options? Pour autant que je sache, il n'y a rien entre threads et processus (Runtime.exec) dans java (pas d'abstraction dans le jvm pour avoir quelque chose comme un "processus java" isolé).

Comment géreriez-vous cela?

EDIT

Merci pour la réponse, encore une fois, un niveau d'indirection le tour est joué.

+2

Le mot que vous cherchez est "thread-safe". –

+0

@Stephen C: merci. Je n'étais pas capable de le remémorer. – LB40

Répondre

11

Vous pouvez vous assurer que la bibliothèque en question n'est utilisée qu'à partir d'un seul thread à la fois. S'il contient des classes instanciables, il est possible de les contenir dans thread local storage. Vous pouvez également créer un wrapper thread-safe autour de lui.

Ces approches pourraient également être combinées, par ex. vous pouvez envelopper la bibliothèque dans une classe (ce serait Facade dans ce cas), qui n'est pas thread-safe en elle-même, mais dont vous accédez aux instances à partir d'un seul thread à la fois.

Mise à jour: comme @Wim souligné, si la bibliothèque gère l'état global, vous devez un fil emballage en toute sécurité pour assurer que les changements soient visibles entre les threads.

+0

Le premier implique vraiment le second. Vous avez besoin de barrières de mémoire pour assurer la cohérence du cache (chaque thread doit avoir la même vue sur n'importe quel état global de la bibliothèque) –

+0

@Wim Très bon point, merci. –

6

Je voudrais créer une façade et ne pas utiliser la bibliothèque directement. La façade devrait alors synchroniser la connexion/les appels à la bibliothèque.

Quelque chose comme:

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

Mise à jour:

Une façade pourrait être le modèle de conception erronée, car il est utilisé pour cacher la fonctionnalité. Wrapper doit servir Design Motif

+3

Facade est un modèle de conception pour un problème légèrement différent - il devrait plutôt être un emballage ou un adaptateur. –

+0

Une façade doit masquer les fonctionnalités et dans ce cas les autres classes. Peut-être avez-vous raison, cela pourrait aussi être un wrapper. –

2

J'écrirait un emballage mince, où toutes les méthodes pertinentes sont synchronisées, et que je serais alors utiliser partout dans mon code, au lieu d'utiliser les classes et les méthodes de la bibliothèque directement. J'évaluerais d'abord, pour quelles parties de la bibliothèque c'est réellement nécessaire. Parfois, une alternative peut être d'utiliser des instances séparées des objets de la bibliothèque pour chaque thread. Mais dans ce cas, les instances ne peuvent pas être partagées entre les threads.

+0

En alternative aux méthodes synchronisées, vous pouvez utiliser des verrous (par exemple ReentrantReadWriteLock) pour réduire les goulots d'étranglement, à condition de connaître le comportement de librarie et de décider quand utiliser ReadLock et WriteLock. – Sylar

+1

@Sebastian: Peut être fait, si vous en savez assez sur la bibliothèque. Peut-être qu'il devrait être noté, que si cela conduit à plusieurs objets de verrouillage, alors évidemment, vous devrez également veiller à éviter les blocages. –

3

Beaucoup dépend de la taille de la bibliothèque et de l'usage que vous en faites. La première chose à faire est d'évaluer où vous pouvez réellement avoir des problèmes de concurrence. Juste parce que vous utilisez la bibliothèque dans plus d'un thread ne signifie pas qu'il ne peut pas être utilisé dans plusieurs threads. Recherchez les éléments de l'API qui indiquent spécifiquement que "ce n'est pas thread-safe" et si vous utiliserez cette partie de l'API, vous devrez la synchroniser vous-même. La solution la plus simple consiste à créer une classe wrapper qui synchronise toutes les méthodes. Pour un exemple, regardez la source à partir des utilitaires de collection (tels que Collections.synchronizedList, ect.).

+1

Notez cependant que les bibliothèques _not_ conçues avec la sécurité des threads indiquent rarement explicitement que "ceci n'est pas thread-safe" dans leur doc API :-( –

2

Regardez comment un problème similaire est résolu dans Collections API. Toutes les collections ne sont pas thread-safe par défaut.

Mais quand vous avez besoin d'une collection thread-safe vous obtenez juste avec

Collections.synchronizedCollection(unsafeCollection) 

La mise en œuvre est caché de l'utilisateur et ce n'est pas une partie de l'API. Vous pouvez aller de la même manière.

Questions connexes