Y a-t-il quelque chose qui cloche avec la sécurité du thread de ce code java? Les threads 1-10 ajoutent des nombres via sample.add(), et Threads 11-20 appellent removeAndDouble() et impriment les résultats sur stdout. Je me rappelle du fond de mon esprit que quelqu'un a dit que l'assignation d'un item de la même manière que dans removeAndDouble() en l'utilisant en dehors du bloc synchronisé peut ne pas être thread safe. Que le compilateur peut optimiser les instructions afin qu'elles se produisent hors séquence. est-ce le cas ici? Ma méthode removeAndDouble() est-elle dangereuse?Affectation d'un objet à un champ défini en dehors d'un bloc synchronisé - est-il sûr pour les threads?
Y a-t-il autre chose qui ne va pas dans une perspective de concurrence avec ce code? J'essaie d'avoir une meilleure compréhension de la concurrence et du modèle de mémoire avec Java (1.6 vers le haut).
import java.util.*;
import java.util.concurrent.*;
public class Sample {
private final List<Integer> list = new ArrayList<Integer>();
public void add(Integer o) {
synchronized (list) {
list.add(o);
list.notify();
}
}
public void waitUntilEmpty() {
synchronized (list) {
while (!list.isEmpty()) {
try {
list.wait(10000);
} catch (InterruptedException ex) { }
}
}
}
public void waitUntilNotEmpty() {
synchronized (list) {
while (list.isEmpty()) {
try {
list.wait(10000);
} catch (InterruptedException ex) { }
}
}
}
public Integer removeAndDouble() {
// item declared outside synchronized block
Integer item;
synchronized (list) {
waitUntilNotEmpty();
item = list.remove(0);
}
// Would this ever be anything but that from list.remove(0)?
return Integer.valueOf(item.intValue() * 2);
}
public static void main(String[] args) {
final Sample sample = new Sample();
for (int i = 0; i < 10; i++) {
Thread t = new Thread() {
public void run() {
while (true) {
System.out.println(getName()+" Found: " + sample.removeAndDouble());
}
}
};
t.setName("Consumer-"+i);
t.setDaemon(true);
t.start();
}
final ExecutorService producers = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
final int j = i * 10000;
Thread t = new Thread() {
public void run() {
for (int c = 0; c < 1000; c++) {
sample.add(j + c);
}
}
};
t.setName("Producer-"+i);
t.setDaemon(false);
producers.execute(t);
}
producers.shutdown();
try {
producers.awaitTermination(600, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
sample.waitUntilEmpty();
System.out.println("Done.");
}
}
Bon appel sur 'notifyAll'. –
Oui bon appel sur notifyAll() et le délai d'attente. – Mike