87 votes

Le thread ThreadPoolExecutor est-il sécurisé?

ExecutorService garantit-il la sécurité des threads?

Je vais soumettre des travaux de différents threads au même ThreadPoolExecutor. Dois-je synchroniser l'accès à l'exécuteur avant d'interagir / de soumettre des tâches?

61voto

Luke Usherwood Points 687

(Contrairement à d'autres réponses) le fil-contrat de sécurité est documenté: regarder dans l' interface javadoc (par opposition à la javadoc de méthodes). Par exemple, au bas de la ExecutorService javadoc vous trouverez:

Consistance de la mémoire effets: les Actions dans un thread avant l' présentation d'un Exécutable ou Remboursables par anticipation de la tâche à un ExecutorService passer-devant de toutes les mesures prises par l'équipe, qui à son tour arrivera-avant le résultat est récupéré via l'Avenir.get().

C'est suffisant pour répondre à cette:

"dois-je synchroniser l'accès à l'exécuteur avant d'avoir des relations/la soumission de tâches?"

Non, vous ne le font pas. C'est bien beau de construire et de soumettre des travaux à tout (correctement mis en œuvre) ExecutorService sans synchronisation externe. C'est l'un des principaux objectifs de la conception.

ExecutorService est une concurrente de l'utilitaire, c'est à dire qu'il est conçu pour fonctionner dans la plus grande mesure, sans nécessiter de synchronisation, pour la performance. (Synchronisation des causes thread-les conflits, qui peuvent dégrader le multi-threading d'efficacité - en particulier lors de la mise à l'échelle jusqu'à un grand nombre de threads.)

Il n'y a aucune garantie quant à quel moment dans l'avenir, les tâches s'exécuter ou complète (certains peuvent même exécuter immédiatement sur le même thread que celui qui les a soumis); toutefois, le thread de travail est la garantie d'avoir vu tous les effets que la soumission thread a effectué jusqu'au moment de la soumission. Donc (le thread qui s'exécute) votre tâche peut également en toute sécurité lire toutes les données de sa création pour utilisation sans synchronisation, des classes thread-safe, ou toute autre forme de publication". La loi de la soumission de la tâche est en soi suffisante pour sûr "publication" de l'entrée de données de la tâche. Vous avez juste besoin de s'assurer que les données d'entrée ne sera pas modifié en aucune façon et que la tâche est en cours d'exécution.

De même, lorsque vous récupérer le résultat de la tâche, le retour par Future.get(), la récupération de fil sera assuré de voir tous les effets faite par l'exécuteur de la thread de travail (dans les deux cas, le résultat renvoyé, plus les effets secondaires des modifications de la travailleur-thread peut avoir fait).

Ce contrat implique aussi qu'il est bien pour les tâches elles-mêmes à soumettre davantage de tâches.

"Le ExecutorService garantir la sécurité des threads ?"

Maintenant cette partie de la question est beaucoup plus général. Par exemple, ne pouvait pas trouver toute déclaration d'un thread-contrat de sécurité à propos de la méthode shutdownAndAwaitTermination - mais je remarque que l'exemple de code dans la Javadoc ne pas utiliser la synchronisation. (Bien que peut-être il y a caché hypothèse que l'arrêt est provoqué par le même thread qui a créé l'Exécuteur testamentaire, et pas, par exemple, un thread de travail?)

BTW, je vous recommande le livre "Java Simultanéité Dans la Pratique" pour une bonne grounder sur le monde de la programmation simultanée.

31voto

Kevin Bourrillion Points 19677

Il est vrai que les classes JDK en question ne semblent pas constituer une garantie explicite de la soumission de tâches thread-safe. Cependant, dans la pratique, toutes les implémentations d'ExecutorService dans la bibliothèque sont effectivement thread-safe. Je pense qu'il est raisonnable de dépendre de cela. Étant donné que tout le code implémentant ces fonctionnalités a été placé dans le domaine public, il n’ya aucune motivation pour quiconque de le réécrire complètement d’une manière différente.

9voto

Adamski Points 29884

Votre question est plutôt ouvert: Toute l' ExecutorService interface n'est garantie que certaines thread quelque part, le processus de la soumise Runnable ou Callable de l'instance.

Si la soumise Runnable / Callable fait référence à une structure de données partagées qui est accessible à partir d'autres Runnable / Callables cas (pouvant être traitées simultanément par différents threads), alors il est de votre responsabilité d'assurer la sécurité des threads à travers cette structure de données.

Pour répondre à la deuxième partie de votre question, oui, vous aurez accès à la ThreadPoolExecutor avant de soumettre des tâches; par exemple,

BlockingQueue<Runnable> workQ = new LinkedBlockingQueue<Runnable>();
ExecutorService execService = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.SECONDS, workQ);
...
execService.submit(new Callable(...));

MODIFIER

En fonction de Brian commentaire et dans les cas que j'ai mal compris votre question: Soumission de tâches à partir de plusieurs threads producteurs à l' ExecutorService généralement être thread-safe (bien que n'étant pas explicitement mentionné dans l'interface de l'API d'aussi loin que je peux dire). Toute mise en œuvre, qui n'offre pas la sécurité des threads serait inutile dans un environnement multi-thread (comme plusieurs producteurs et plusieurs consommateurs est assez paradigme), et c'est précisément de ce qu' ExecutorService (et le reste de l' java.util.concurrent) a été conçu pour.

6voto

Scott S. McCoy Points 667

Pour ThreadPoolExecutor la réponse est tout simplement oui. ExecutorService n'a pas de mandat ou autrement garantir que toutes les implémentations sont thread-safe, et il ne peut pas car il est une interface. Ces types de contrats sont en dehors de la portée d'une interface Java. Toutefois, ThreadPoolExecutor à la fois est et n'est clairement documenté comme étant thread-safe. De plus, en ThreadPoolExecutor gère c'est le travail de la file d'attente à l'aide de java.util.concurrent.BlockingQueue qui est une interface que les demandes de toutes les implémentations sont thread-safe. Tout java.util.concurrent.* de la mise en œuvre de l' BlockingQueue peut raisonnablement supposer être thread-safe. Tout non-standard de mise en œuvre ne peut pas, bien que ce serait carrément stupide si quelqu'un était de fournir un BlockingQueue la mise en œuvre de la file d'attente qui n'était pas thread-safe.

Si la réponse à votre question titre est clairement oui. La réponse à la suite du corps de votre question est probablement, comme il y a quelques différences entre les deux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X