Có điều gì sai với sự an toàn của chuỗi java này không? Chủ đề 1-10 thêm số qua sample.add(), và Chủ đề 11-20 gọi removeAndDouble() và in kết quả thành stdout. Tôi nhớ lại từ phía sau trong tâm trí của tôi rằng ai đó nói rằng chỉ định mục theo cùng một cách như tôi đã có trong removeAndDouble() bằng cách sử dụng nó bên ngoài khối đồng bộ có thể không được thread an toàn. Trình biên dịch có thể tối ưu hóa các hướng dẫn để chúng xuất hiện ngoài trình tự. Đó có phải là trường hợp ở đây không? Phương thức removeAndDouble() của tôi có an toàn không?Gán một đối tượng cho một trường được xác định bên ngoài một khối được đồng bộ hóa - nó có phải là chủ đề an toàn không?
Có điều gì khác không đúng với phối cảnh đồng thời với mã này không? Tôi đang cố gắng để có được một sự hiểu biết tốt hơn về concurrency và mô hình bộ nhớ với java (1.6 trở lên).
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.");
}
}
Cuộc gọi tốt trên 'notifyAll'. –
Có cuộc gọi tốt trên notifyAll() và thời gian chờ chờ. – Mike