2017-08-02 7 views
-3

Je sais que c'est clairement une condition de concurrence. Mais quelles sont les choses possibles qui peuvent arriver?Quel est le pire qui puisse arriver en état de course java?

class Blah { 
    List<String> stuff; 
    public List<String> getStuff() { 
     return stuff 
    } 
    public void setStuff(List<String> newValue) { 
     this.stuff = newValue 
    } 
} 

b = new Blah(); 
// Thread one 
b.setStuff(getListFromSomeNetworkResource()); 
for (String c : b.getStuff()) { 
    // Work with c 
} 


// Thread two 
b.setStuff(getListFromSomeNetworkResource()); 
for (String c : b.getStuff()) { 
    // Work with c 
} 
  1. Cela peut-il RuntimeException jeter?
  2. Est-ce que ce segfault se sépare de jvm?
  3. Est-ce que cela peut provoquer une erreur de segmentation?
  4. Cela dépend du processeur. Et si c'est un processeur Intel Xeon?
  5. Est-ce que cela peut lancer une exception NullPointer?
  6. Discussion 2 peut lire le contenu défini par fil 1 et vice versa si la fonction retourne réellement différentes valeurs

Je comprends que c'est une condition de course et n'écrire un tel code. Mais comment convaincre les autres de ne pas le faire?

Mise à jour:

Hypothèses:

  1. getListFromSomeNetworkResource() retourne toujours une nouvelle ArrayList. La taille peut être 0 ou plus.
  2. getListFromSomeNetworkResource() est thread-safe.
+0

Downvoters, s'il vous plaît laisser un commentaire – balki

Répondre

0

Est-ce que cela lance RuntimeException?

Non, sigetListFromSomeNetworkResource() est thread-safe et ne retourne pas null.

Est-ce que ce segfault se produit?

Est-ce que cela peut endommager l'un des threads?

Cela dépend du processeur. Et si c'est un processeur Intel Xeon?

No.

cela peut lancer une exception NullPointer?

uniquement si getListFromSomeNetworkResource() peut renvoyer null.

Discussion 2 peut lire le contenu défini par fil 1 et vice versa si la fonction retourne réellement différentes valeurs

oui, cela est susceptible de se produire.

-1

Le danger serait un ordre tel que:

  1. Enfiler un: b.setStuff(getListFromSomeNetworkResource());
  2. Discussion deux: b.setStuff(getListFromSomeNetworkResource());
  3. Enfiler un: b.stuff.iterator() (via b.getStuff(), au début de la pour boucle

Dans ce cas, enfilez un peut être itérer sur la liste que le fil deux ensemble. Cette publication, du thread 2 au thread 1, a été faite sans synchronisation - c'est une course de données. En supposant que cette liste n'est pas elle-même thread-safe, beaucoup de choses peuvent arriver. Le problème principal serait que certains états de la liste soient visibles pour en entraîner un, mais pas tous, en raison de cette course de données.

  • Il peut lancer certaines RuntimeException. Par exemple, peut-être un champ pense que la liste a n éléments en raison d'un redimensionnement. Mais le nouveau tableau qui vient de ce redimensionnement ne l'a pas fait, donc vous vous retrouvez avec un ArrayIndexOutOfBoundsException
  • Il peut lancer une exception NullPointerException pour un certain nombre de raisons; peut-être une liste liée, et l'une des écritures de référence n'a pas à Enfiler un

Il ne devrait pas causer de segfaults: ceux qui ne peuvent venir au sujet de bogues dans la machine virtuelle Java, mais jamais des bugs dans votre code . Cela peut dépendre du processeur, dans la mesure où les processeurs peuvent traiter différemment des tâches telles que le vidage de la mémoire d'un cache de processeur à un autre - c'est l'une des raisons pour lesquelles une publication non sécurisée peut vous empêcher de voir certaines des données un fil a écrit, d'un autre fil. Il y a des moyens de forcer ces caches à se rincer; la façon de les spécifier en Java est à travers les différents mécanismes de synchronisation de données (acquisition de verrous, utilisation de champs volatiles, etc.).

+0

>> thread un peut être itérer sur la liste que le fil deux ensemble Est-ce vraiment possible? L'itérateur n'est-il pas local à l'objet et les deux threads ont-ils des objets différents? – balki

+0

Les deux threads partagent la même instance 'b', cependant, et les deux peuvent partager la même référence' b.stuff'. L'itérateur est en effet thread-local, mais sa liste de sauvegarde ne l'est pas. Dans mon exemple ci-dessus, avec les étapes ordonnées comme je les ai, pensez à l'objet 'b.stuff' qui fait référence à la troisième étape. – yshavit

+0

Ooh, un downvote drive-by plus d'un mois et demi après. C'est nouveau. :-) Une chance pour un commentaire expliquant? – yshavit