2012-04-26 38 views
11

Các cách có thể làm cho an toàn cho chuỗi mã mà không sử dụng từ khóa synchronized là gì?Mã an toàn chủ đề mà không sử dụng từ khóa `được đồng bộ hóa '?

+2

tại sao lại gần? Một câu hỏi ngắn gọn của nó là – NimChimpsky

+0

@NimChimpsky Tôi cũng không biết, câu hỏi có vẻ hoàn toàn hợp lệ với tôi. Nó chắc chắn là đáng tin cậy, và câu trả lời không phải là một cái gì đó chủ quan. – Malcolm

Trả lời

4

Chỉ có biến/tham chiếu cục bộ cho phương pháp. Hoặc đảm bảo rằng bất kỳ biến mẫu nào đều không thay đổi.

+0

Biến không thể thay đổi không thể chấp nhận được? – duffymo

+0

@duffymo đã chỉnh sửa – NimChimpsky

+0

tốt - ngắn gọn và chính xác. –

4

Bạn có thể làm cho mã của bạn an toàn bằng cách làm cho tất cả dữ liệu không thay đổi được, nếu không có khả năng thay đổi, mọi thứ đều an toàn chỉ. Thứ hai, bạn có thể muốn có một cái nhìn tại API đồng thời java có cung cấp để cung cấp khóa đọc/ghi mà thực hiện tốt hơn trong trường hợp có rất nhiều độc giả và một vài nhà văn. Từ khóa đồng bộ hóa thuần túy cũng sẽ chặn hai người đọc.

7

Trên thực tế, rất nhiều cách:

  1. Không cần đồng bộ ở tất cả nếu bạn không có nhà nước có thể thay đổi.
  2. Không cần đồng bộ hóa nếu trạng thái có thể thay đổi được giới hạn trong một chuỗi đơn lẻ. Điều này có thể được thực hiện bằng cách sử dụng các biến cục bộ hoặc java.lang.ThreadLocal.
  3. Bạn cũng có thể sử dụng bộ đồng bộ được tích hợp sẵn. java.util.concurrent.locks.ReentrantLock có chức năng tương tự như khóa bạn truy cập khi sử dụng các khối và phương pháp synchronized và thậm chí còn mạnh hơn nữa.
+1

Tôi thích (2), nhưng tôi không chắc liệu nó có khả năng thực hiện thông điệp mà không sử dụng từ khóa 'đồng bộ' hay không. Tôi có thể tạo hàng đợi của người tiêu dùng sản xuất mà không cần 'đồng bộ' không? –

+1

Đừng bận tâm - tôi có thể, bằng cách sử dụng java.util.concurrent.Semaphore. –

+1

@MartinJames Bất kỳ lớp Đồng thời nào như Queues và Exchangers đều có thể được sử dụng mà không cần đồng bộ hóa. (Họ sử dụng Khóa thay thế) Disrupter hỗ trợ nhắn tin mà không cần khóa hoặc đồng bộ hóa. (Tôi có một thư viện mà thực hiện điều này là tốt) –

-2

Tại sao bạn cần làm điều đó?

Chỉ sử dụng biến cục bộ/tham chiếu sẽ không giải quyết được hầu hết các nhu cầu kinh doanh phức tạp. Ngoài ra, nếu biến mẫu là bất biến, các tham chiếu của chúng vẫn có thể được thay đổi bởi các luồng khác.

Một tùy chọn là sử dụng một cái gì đó như là SingleThreadModel, nhưng tùy chọn này không được khuyến khích và không dùng nữa.

u cũng có thể nhìn vào api đồng thời theo đề nghị trên bởi Kal

+0

"nếu biến mẫu là bất biến, tài liệu tham khảo của họ vẫn có thể được thay đổi" không họ không thể – NimChimpsky

+0

bạn có thể giải thích điều đó không. Làm thế nào tôi thấy nó là nếu tôi có một biến instanace Chuỗi s = "xyz", thread1 của tôi có thể thay đổi tham chiếu của nó để s = "abc"; và thread2 bây giờ sẽ nhận được s = "abc" – Kshitij

+0

s là một tham chiếu, nó đã thay đổi, nó không thay đổi, bạn sẽ cần "chuỗi cuối cùng s" – NimChimpsky

1

Để duy trì khả năng dự báo bạn hoặc phải đảm bảo tất cả các truy cập dữ liệu có thể thay đổi được thực hiện tuần tự hoặc xử lý các vấn đề gây ra bởi truy cập song song.

Bảo vệ tổng thể nhất sử dụng từ khóa synchronized. Ngoài ra, có ít nhất hai lớp khả năng, mỗi lớp có lợi ích của chúng.

Locks/Semaphores

Đây có thể rất hiệu quả. Ví dụ, nếu bạn có một cấu trúc được đọc bởi nhiều chủ đề nhưng chỉ được cập nhật bởi một chủ đề bạn có thể tìm thấy ReadWriteLock hữu ích.

Khóa có thể hiệu quả hơn nhiều nếu bạn chọn khóa để khớp với thuật toán.

Atomics

Sử dụng AtomicReference ví dụ thường có thể cung cấp hoàn toàn khóa chức năng miễn phí. Điều này thường có thể mang lại lợi ích to lớn.

Lý do đằng sau nguyên tử là cho phép chúng thất bại nhưng để cho bạn biết chúng không thành công theo cách bạn có thể xử lý.

Ví dụ: nếu bạn muốn thay đổi giá trị, bạn có thể đọc nó và sau đó viết giá trị mới miễn là nó vẫn là giá trị cũ. Điều này được gọi là "so sánh và đặt" hoặc cas và thường có thể được triển khai trong phần cứng và vì vậy cực kỳ hiệu quả. Tất cả những gì bạn cần là một cái gì đó như:

long old = atomic.get(); 
while (!atomic.cas(old, old+1)) { 
    // The value changed between my get and the cas. Get it again. 
    old = atomic.get(); 
} 

Lưu ý, tuy nhiên, khả năng dự đoán đó không phải lúc nào cũng là yêu cầu.

Các vấn đề liên quan