0
votes

Pourquoi sommes-nous ici, spécifiquement, en train de dire que ArrayList n'est pas thread-safe?

Description: Si nous utilisons la même référence d'objet parmi plusieurs threads, aucun objet n'est thread-safe. De même, si une référence de collection est partagée entre plusieurs threads, cette collection n'est pas thread puisque d'autres threads peuvent y accéder. Alors, pourquoi disons-nous ici spécifiquement qu'ArrayList n'est pas thread-safe? Qu'en est-il des autres collections?


4 commentaires

Si nous utilisons la même référence d'objet parmi plusieurs threads, aucun objet n'est thread-safe. Non, votre hypothèse est fausse


Si deux threads sont exécutés simultanément pour modifier une valeur dans la référence d'objet, cela ne crée-t-il pas une interférence? Cela ne signifie-t-il pas qu'ils ne sont pas protégés contre les menaces?


pas vraiment non, si c'est protégé par des verrous par exemple, alors il est thread-safe


L'état mutable partagé n'est jamais thread-safe. Il doit être protégé de manière appropriée pour gérer l'accès aux threads ou être rendu immuable. C'est pourquoi les objets immuables et le style fonctionnel sont souhaitables - les objets immuables sont toujours thread-safe. Ils viennent au prix d'une plus grande consommation de mémoire.


3 Réponses :


1
votes

Je n'ai pas vérifié mais je pense que toutes les implémentations standard de Collection indiquent si elles sont thread-safe ou non. Vous savez donc si vous pouvez partager cette collection entre différents threads sans synchronisation.

CopyOnWriteArrayList, par exemple, est une implémentation de List sécurisée pour les threads.


2 commentaires

Donc, s'il s'agit d'une collection thread-safe, sans la déclarer synchronisée, nous pouvons l'utiliser entre plusieurs threads pour éviter les interférences. Pour cette raison, nous disons qu'ArrayList n'est pas thread-safe. Ai-je raison?


Il peut y avoir des interférences comme par exemple le blocage (un appel de méthode attend qu'un autre appel dans un thread différent soit terminé). De telles mises en garde doivent être documentées dans la classe «JavaDoc. Mais il n'y aura pas de données corrompues ou d'exceptions ConcurrentModificationExceptions ou quoi que ce soit de ce genre.



0
votes

ArrayList n'est pas synchronisé dans l'implémentation. Lorsqu'un objet n'est pas synchronisé, cela signifie qu'il n'est pas verrouillé tout en étant modifié structurellement. Une modification structurelle est toute opération qui ajoute ou supprime un ou plusieurs éléments, ou redimensionne explicitement le tableau de support; la simple définition de la valeur d'un élément n'est pas une modification structurelle. Ce à quoi vous faites référence est un tableau auquel les éléments sont ajoutés ou supprimés et qui peuvent être modifiés, ce qui diffère du fait que sa valeur est définie.

La référence concerne le pointeur du début du tableau mais il est question de combien d'éléments y a-t-il et d'avoir un objet non synchronisé en cours de modification dans le sens des éléments alors que les éléments sont itérés par un autre thread l'intégrité de les éléments de la liste sont difficiles à garantir. J'espère avoir été en mesure de transmettre le message clairement.

Recherchez plus de détails ici dans Oracle: Array List et ConcurrentModificationException < / p>

ArrayList:

Notez que cette implémentation n'est pas synchronisée. Si plusieurs threads accèdent simultanément à une instance ArrayList et qu'au moins un des threads modifie la liste structurellement, elle doit être synchronisée en externe. (Une modification structurelle est toute opération qui ajoute ou supprime un ou plusieurs éléments, ou redimensionne explicitement le tableau de support; le simple fait de définir la valeur d'un élément n'est pas une modification structurelle.) Ceci est généralement accompli en synchronisant sur un objet qui encapsule naturellement le liste. Si aucun objet de ce type n'existe, la liste doit être «encapsulée» à l'aide de la méthode Collections.synchronizedList.

ConcurrentModificationException:

Notez que le comportement à échec rapide ne peut pas être garanti car il est, d'une manière générale, impossible de faire des garanties fermes en présence de modifications concurrentes non synchronisées.


0 commentaires

2
votes

Vous avez mal compris la signification de «thread-safe».

Quand nous disons que «la classe X est thread-safe», nous ne disons pas que vous n’avez pas à vous soucier de la sécurité des threads d’un programme qui l'utilise. Si vous construisez un programme en utilisant uniquement des objets thread-safe, cela ne garantit pas que votre programme sera thread-safe.

Alors, qu'est-ce que garantit ?

Supposons que vous ayez une Liste . Supposons que deux threads, A et B, écrivent chacun des valeurs différentes dans le même index de la liste, supposons qu'un thread C lit à partir de cet index, et supposons qu'aucun de ces trois threads n'utilise de synchronisation.

Si la liste est "thread-safe", alors vous pouvez être assuré que le thread C obtiendra l'une des trois valeurs possibles:

  • La valeur que le thread A a écrite,
  • La valeur que le thread B a écrite,
  • La valeur stockée à cet index avant l'écriture du thread A ou du thread B.

Si la liste n'est pas thread-safe, alors l'une de ces trois mêmes choses pourrait se produire, mais aussi, d'autres choses pourraient se produire:

  • Le thread C pourrait obtenir une valeur qui ne figurait jamais dans la liste,
  • La liste pourrait se comporter de manière cassée à l'avenir pour le thread C même si aucun autre thread ne continue de l'utiliser,
  • Le programme pourrait planter,
  • etc. (Je ne sais pas combien d'autres choses étranges pourraient arriver.)

Quand nous disons qu'une classe est "thread-safe", nous disons qu'elle se comportera toujours de manière prévisible et raisonnable, même lorsque ses méthodes sont appelées simultanément par plusieurs threads.

Si vous écrivez un programme qui utilise une liste "thread-safe", et si cela dépend du thread C lisant une valeur particulière des trois possibilités que j'ai énumérées ci-dessus, alors votre programme a un problème de sécurité des threads, même si la liste elle-même ne le fait pas.


2 commentaires

J'ai compris la sécurité des threads de la manière suivante: si A, B font tous les deux une modification structurelle sur la liste, ils le font l'un après l'autre. Je veux dire, la liste serait verrouillée pour A jusqu'à ce qu'elle termine son opération, puis pour B. Est-ce une bonne compréhension?


@manikantanvsr, oubliez la «modification structurelle». J'ai volontairement choisi un exemple ci-dessus dans lequel il n'est pas nécessaire que la structure de la liste change. Tout accès simultané à un objet "unsafe" a le potentiel de planter votre programme ou pire * si au moins un de ces accès est une écriture. [* Pour «pire», imaginez une application vitale qui prend une mauvaise décision, un programme qui stocke de mauvaises données dans une base de données vitale, etc.]