Il s’agit d’un sondage de toutes sortes sur les problèmes courants d’accès concurrentiel en Java. Un exemple pourrait être la condition de blocage ou de course classique ou peut-être EDT filetage bugs dans la balançoire. Je m’intéresse aussi bien dans un éventail de problèmes possibles, mais aussi dans quels sont les enjeux sont les plus communs. Alors, s’il vous plaît laissez une réponse spécifique d’un bug de simultanéité de Java par commentaire et votez pour si vous voyez un que vous avez rencontrés.
Réponses
Trop de publicités?Mon problème de simultanéité plus douloureuse #1 a déjà produit quand les deux bibliothèques de différents open source fait quelque chose comme ceci :
À première vue, cela ressemble à un exemple assez trivial de synchronisation. Cependant ; parce que les chaînes sont internées dans Java, la chaîne littérale « LOCK » s’avère pour être la même instance de java.lang.String (même si elles sont déclarées totalement indifféremment les uns des autres.) Le résultat est évidemment mauvais.
La plus commune des problèmes de simultanéité que j'ai vu, est de ne pas se rendre compte qu'un champ écrite par un seul thread est pas la garantie d'être vu par un autre thread. Une application courante de ce:
class MyThread extends Thread {
private boolean stop = false;
public void run() {
while(!stop) {
doSomeWork();
}
}
public void setStop() {
this.stop = true;
}
}
Tant que stop n'est pas volatile ou setStop
et run
ne sont pas synchronisées, ce n'est pas garanti. Cette erreur est particulièrement diabolique comme dans 99.999%, il ne sera pas question, dans la pratique, comme le lecteur thread va finalement voir le changement - mais nous ne savons pas combien de temps il l'a vu.
Un problème commun est à l’aide de classes comme calendrier et SimpleDateFormat partir de plusieurs threads (souvent par leur cache dans une variable statique) sans synchronisation. Ces classes ne sont pas thread-safe donc accès multithread finalement provoque des problèmes étranges avec état incohérent.
Double-Vérifier Le Verrouillage. Par et grand.
Le paradigme qui j'ai commencé à apprendre les problèmes de quand je travaillais à la BEA, c'est que les gens vont vérifier un singleton de la façon suivante:
public Class MySingleton {
private static MySingleton s_instance;
public static MySingleton getInstance() {
if(s_instance == null) {
synchronized(MySingleton.class) { s_instance = new MySingleton(); }
}
return s_instance;
}
}
Cela ne fonctionne jamais, parce qu'un autre thread ont peut-être eu dans le bloc synchronisé et s_instance n'est plus nulle. Ainsi, l'accroissement naturel est alors de la faire:
public static MySingleton getInstance() {
if(s_instance == null) {
synchronized(MySingleton.class) {
if(s_instance == null) s_instance = new MySingleton();
}
}
return s_instance;
}
Cela ne fonctionne pas non plus, parce que la Mémoire Java Modèle ne prend pas en charge. Vous devez déclarer s_instance comme volatile pour le faire fonctionner, et même alors, il ne fonctionne que sur Java 5.
Les gens qui ne sont pas familiers avec les subtilités de la Mémoire Java Modèle de ce mess up tout le temps.