trong cố gắng để cải thiện sự hiểu biết của tôi về vấn đề đồng thời, tôi đang xem xét kịch bản sau đây (Edit: Tôi đã thay đổi ví dụ từ sách để Runtime, đó là gần gũi hơn với những gì tôi đang cố gắng):Xác định phạm vi đồng bộ hóa?
public class Example {
private final Object lock = new Object();
private final Runtime runtime = Runtime.getRuntime();
public void add(Object o) {
synchronized (lock) { runtime.exec(program + " -add "+o); }
}
public Object[] getAll() {
synchronized (lock) { return runtime.exec(program + " -list "); }
}
public void remove(Object o) {
synchronized (lock) { runtime.exec(program + " -remove "+o); }
}
}
Vì nó là viết tắt, mỗi phương pháp là bởi thread an toàn khi được sử dụng độc lập. Bây giờ, những gì tôi đang cố gắng tìm ra là làm thế nào để xử lý nơi lớp gọi điện thoại muốn gọi:
for (Object o : example.getAll()) {
// problems if multiple threads perform this operation concurrently
example.remove(b);
}
Nhưng như đã nói, không có gì bảo đảm rằng nhà nước sẽ được thống nhất giữa các cuộc gọi đến GetAll() và các cuộc gọi để xóa(). Nếu nhiều chủ đề gọi điều này, tôi sẽ gặp rắc rối. Vì vậy, câu hỏi của tôi là - Làm cách nào để tôi cho phép nhà phát triển thực hiện thao tác theo cách an toàn? Lý tưởng nhất là tôi muốn thực thi an toàn luồng theo cách gây khó khăn cho nhà phát triển để tránh/bỏ lỡ, nhưng đồng thời không phức tạp để đạt được. Tôi có thể nghĩ đến ba tùy chọn cho đến thời điểm này:
A: Tạo khóa 'this', vì vậy đối tượng đồng bộ hóa có thể truy cập vào mã gọi, sau đó có thể bọc các khối mã. Nhược điểm: Khó thực thi tại thời gian biên dịch:
synchronized (example) {
for (Object o : example.getAll()) {
example.remove(b);
}
}
B: Đặt mã kết hợp vào lớp Example - và có lợi để tối ưu hóa việc triển khai, như trong trường hợp này. Nhược điểm: Đau để thêm tiện ích mở rộng và khả năng trộn logic không có liên quan:
public class Example {
...
public void removeAll() {
synchronized (lock) { Runtime.exec(program + " -clear"); }
}
}
C: Cung cấp lớp đóng. Nhược điểm: Mã dư thừa, có khả năng quá hào phóng của một khối đồng bộ hóa, thực tế có thể làm cho deadlocks dễ dàng hơn:
public interface ExampleClosure {
public void execute(Example example);
}
public Class Example {
...
public void execute(ExampleClosure closure) {
synchronized (this) { closure.execute(this); }
}
}
example.execute(new ExampleClosure() {
public void execute(Example example) {
for (Object o : example.getAll()) {
example.remove(b);
}
}
}
);
Tôi đang thiếu cái gì? Làm thế nào đồng bộ hóa nên được scoped để đảm bảo mã là thread an toàn?
Xin lỗi, ví dụ này có một chút không rõ ràng. Tôi đã xóa tham chiếu đến Danh sách. Tôi chỉ cố gắng tìm ra cách tốt nhất để giải quyết: Blah result = example.method1(); example.method2 (kết quả); trong đó lời gọi tới method2 có thể gây ra vấn đề bởi vì inbetween method1 và method2, một thread khác đã đi và được gọi là method3(). – Mike