Tôi khá mới đối với chương trình Scala và chức năng, và tôi thích ý tưởng sử dụng các đối tượng bất biến tôi có thể tránh được nhiều cạm bẫy an toàn. Một điều vẫn ám ảnh tôi, và đó là ví dụ cổ điển được sử dụng để dạy an toàn luồng - bộ đếm được chia sẻ. Tôi đã tự hỏi nếu nó có thể thực hiện một bộ đếm thread-an toàn (một truy vấn yêu cầu trong ví dụ này), sử dụng các đối tượng bất biến, và khái niệm chức năng, và tránh đồng bộ hóa hoàn toàn.Cách chức năng để thực hiện một bộ chia sẻ an toàn chủ đề
Vì vậy, để tham khảo đây là lần đầu tiên các phiên bản có thể thay đổi cổ điển của bộ đếm (xin lỗi cho biến thành viên công cộng, chỉ cho ngắn gọn trong những ví dụ)
thể thay đổi, không chủ đề phiên bản an toàn:
public class Servlet extends HttpServlet {
public int requestCount = 0;
@Override
public void service(ServletRequest req, ServletResponse res) throws ... {
requestCount++; //thread unsafe
super.service(req, res);
}
}
Biên Đổi, Classic chủ đề phiên bản an toàn: (hoặc vì vậy tôi hy vọng ...)
public class Servlet extends HttpServlet {
public volatile int requestCount = 0;
@Override
public void service(ServletRequest req, ServletResponse res) throws ... {
synchronized (this) {
requestCount++;
}
super.service(req, res);
}
}
Tôi đã tự hỏi nếu có một cách sử dụng các đối tượng bất biến, và biến biến động để đạt được an toàn thread mà không đồng bộ hóa.
Vì vậy, đây là nỗ lực ngây thơ của tôi. Ý tưởng là để có một đối tượng bất biến cho bộ đếm và chỉ thay thế tham chiếu đến nó bằng biến biến động. Cảm thấy cá, nhưng đáng để bắn.
Chủ:
public class Incrementer {
private final int value;
public Incrementer(final int oldValue) {
this.value = oldValue + 1;
}
public Incrementer() {
this.value = 0;
}
public int getValue() {
return value;
}
}
servlet Modified:
public class Servlet extends HttpServlet {
public volatile Incrementer incrementer = new Incrementer();
@Override
public void service(ServletRequest req, ServletResponse res) throws ... {
incrementer = new Incrementer(incrementer.getValue());
super.service(req, res);
}
}
Tôi có một cảm giác mạnh mẽ này cũng không phải là thread an toàn, như tôi đang đọc từ incrementer, và có thể nhận được giá trị cũ (ví dụ: nếu tham chiếu đã được thay thế bằng một chuỗi khác). Trong trường hợp nó thực sự không thread an toàn, sau đó tôi tự hỏi nếu có ở tất cả các "chức năng" cách để xử lý như một kịch bản truy cập mà không cần khóa/đồng bộ hóa.
Vì vậy, câu hỏi của tôi (s) là
- Là chủ đề này an toàn bởi bất kỳ cơ hội?
- Nếu có, tại sao?
- Nếu không, có cách nào để thực hiện bộ đếm như vậy mà không đồng bộ hóa không?
Mặc dù mã ví dụ trên là trong Java, trả lời trong Scala là tất nhiên cũng hoan nghênh
Thú vị, tôi chắc chắn AtomicInteger sử dụng tính năng đồng bộ hóa nội bộ nên tôi thậm chí không coi đó là câu trả lời, nhưng nhìn vào mã nguồn có vẻ như nó đang sử dụng một số cách khác (mã gốc) để đạt được mục tiêu: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/atomic/AtomicInteger.java –