2010-09-22 48 views
0

Est-il vrai que si je n'utilise que le type de données immuable, mon programme Java serait sans danger pour les threads?Est-ce que l'utilisation de types de données non modifiables permet de sécuriser un thread de programme Java?

D'autres facteurs affecteront la sécurité du filetage?

**** Apprécierait si peut fournir un exemple. Merci! ** **

+0

Un exemple de quoi? –

+0

@Erick Robertson - Un exemple qui résout tous les problèmes! :) – willcodejavaforfood

+1

@willcodejavaforfood - Apprécierait si peut fournir cet exemple. Merci! –

Répondre

7

La sécurité des threads consiste à protéger les données partagées et les objets immuables sont protégés car ils sont en lecture seule. Bien à part quand vous les créez, créer un objet est sûr pour les threads.

Il est intéressant de noter que la conception d'une application volumineuse utilisant UNIQUEMENT des objets non modifiables pour assurer la sécurité des threads serait difficile.

C'est un sujet compliqué et je vous recommande de lire Java Concurrency in Practice qui est un très bon endroit pour commencer.

+0

Pas difficile en soi, mais une bonne compréhension de la PF est nécessaire et l'utilisation d'un langage fonctionnel le rend beaucoup moins douloureux. – delnan

+0

En fait, il est possible de créer un objet d'une manière non thread-safe. Démarrer un thread depuis le constructeur est un bon moyen de casser la sécurité des threads, par exemple, si le nouveau thread a une référence à l'objet que vous n'avez pas fini de construire. –

+0

@Bill Michell - Oui, et ceci est couvert par Java Concurrency in Practice. Vous devez être conscient de la façon d'utiliser cela dans le consturctor. – willcodejavaforfood

3

C'est vrai. Le problème est que c'est une limitation assez sérieuse à placer sur votre application pour utiliser uniquement les types de données immuables. Vous ne pouvez pas avoir d'objets persistants dont l'état existe entre les threads.

Je ne comprends pas pourquoi vous voudriez le faire, mais cela ne le rend pas moins vrai.

Détails et exemple: http://www.javapractices.com/topic/TopicAction.do?Id=29

2

Si chaque variable est immuable (jamais changé une fois attribué), vous avez en effet un programme de thread-safe trivialement.

Functional programming environnements en tire parti.

Cependant, il est assez difficile de faire de la programmation purement fonctionnelle dans un langage qui ne lui a pas été conçu à partir de zéro.

Un exemple trivial de quelque chose que vous ne pouvez pas faire dans un programme purement fonctionnel est l'utilisation d'une boucle, car vous ne pouvez pas incrémenter un compteur. Vous devez utiliser des fonctions récursives à la place pour obtenir le même effet.

Si vous ne faites que pénétrer dans le monde de la sécurité des threads et de la simultanéité, je recommande chaudement le livre Java Concurrency in Practice, de Goetz. Il est écrit pour Java, mais les problèmes dont il parle sont également pertinents dans d'autres langues, même si les solutions à ces problèmes peuvent être différentes.

+0

Lorsque la question est posée, vous pouvez incrémenter une variable de boucle qui n'existe que dans la fonction locale. Ce serait complètement thread-safe car la variable n'existerait que sur la pile pour ce thread. –

+0

En fait, la question porte sur un programme qui utilise uniquement des types de données immuables. Il existe des façons d'écrire des programmes java sûrs avec des variables mutables, et JCIP en parle pour la plupart. Mais je crois avoir répondu à la question posée. –

0

L'immunité permet la sécurité contre certaines choses qui peuvent mal se passer avec les boîtiers multi-filetés. Plus précisément, cela signifie que les propriétés d'un objet visible à un thread ne peuvent pas être modifiées par un autre thread pendant que ce premier thread l'utilise (puisque ne peut rien changer, alors clairement qu'un autre thread ne le peut pas).

Bien sûr, cela ne fonctionne que dans la mesure où cet objet fonctionne. Si une référence mutable à l'objet est également partagée, alors certains cas de bugs croisés peuvent arriver par quelque chose mettant un nouvel objet là (mais pas tous, car peu importe si un thread fonctionne sur un objet qui a déjà été remplacé , mais encore une fois cela peut être crucial).

En tout, l'immuabilité doit être considérée comme l'une des façons de garantir la sécurité du filetage, mais pas de manière unique ni nécessairement suffisante en soi.

0

Bien que les objets immuables soient d'une aide pour la sécurité des threads, vous pouvez trouver des "variables locales" et "synchroniser" plus pratique pour la programmation dans le monde réel.

0

Tout programme où plus d'un thread n'accède à aucun aspect mutable de l'état du programme sera trivialement sûr pour les threads, car chaque thread peut également être son propre programme distinct. Cependant, le multi-threading utile nécessite généralement une interaction entre les threads, ce qui implique l'existence d'un état partagé mutable.

La clé d'un multithreading sûr et efficace est d'incorporer la mutabilité au «niveau de conception» approprié. Idéalement, chaque aspect de l'état du programme devrait être représentable par une référence immuable (*), mutable, à un objet dont l'état observable est immuable. Un seul thread à la fois peut essayer de changer l'état représenté par une référence mutable particulière. Le multi-threading efficace nécessite que la "couche mutable" dans l'état d'un programme soit suffisamment basse pour que différents threads puissent en utiliser différentes parties. Par exemple, si on a une structure de données AllCustomers immuable et que deux threads tentent simultanément de changer de clients différents, chacun génère une version de la structure de données AllCustomers qui inclut ses propres changements, mais pas celui de l'autre thread. Pas bien. Si AllCustomers était un tableau mutable de CustomerState objets, cependant, il serait possible pour un thread de travailler sur AllCustomers[4] tandis qu'un autre travaillait sur AllCustomers[9], sans interférence. (*) Le chemin enraciné doit exister lorsque l'aspect de l'état devient pertinent et ne doit pas changer tant que l'accès est pertinent. Par exemple, on pourrait concevoir un AddOnlyList<thing> qui contient un thing[][] appelé Arr qui a été initialisé à la taille 32. Lorsque la première chose est ajoutée, Arr[0] serait initialisé, en utilisant CompareExchange, à un tableau de 16 thing. Les 15 prochaines choses iraient dans ce tableau. Lorsque la 17ème chose est ajoutée, Arr[1] serait initialisé en utilisant CompareExchange dans un tableau de taille 32 (qui contiendrait le nouvel élément et les 31 éléments après). Lorsque la 49ème chose est ajoutée, Arr[2] sera initialisé pour 64 articles. Notez que tandis que thing lui-même et les tableaux qu'il contient ne seraient pas totalement immuables, seul le premier accès à un élément serait écrit, et une fois que Arr[x][y] contiendra une référence à quelque chose, il continuera à le faire tant que Arr existe.