Tôi đang tự hỏi cái nào trong số này tốt hơn trong thực tế và tại sao?
Tôi đã thấy rằng Lock
và Condition
(và các concurrent
lớp mới khác ) chỉ là nhiều công cụ hơn cho hộp công cụ. Tôi có thể làm hầu hết mọi thứ tôi cần với chiếc búa vuốt cũ ( synchronized
từ khóa), nhưng thật khó sử dụng trong một số tình huống. Một vài trong số những tình huống khó xử đó trở nên đơn giản hơn nhiều khi tôi thêm nhiều công cụ vào hộp công cụ của mình: một cái vồ cao su, một cây búa bóng, một thanh prybar và một số cú đấm móng tay. Tuy nhiên , búa vuốt cũ của tôi vẫn thấy phần sử dụng của nó.
Tôi không nghĩ rằng cái này thực sự "tốt" hơn cái kia, nhưng mỗi cái lại phù hợp hơn cho các vấn đề khác nhau. Tóm lại, mô hình đơn giản và tính chất định hướng phạm vi synchronized
giúp bảo vệ tôi khỏi các lỗi trong mã của tôi, nhưng những lợi thế tương tự đôi khi lại gây trở ngại trong các tình huống phức tạp hơn. Đây là những kịch bản phức tạp hơn mà gói đồng thời được tạo ra để giúp giải quyết. Nhưng sử dụng các cấu trúc mức cao hơn này đòi hỏi quản lý rõ ràng và cẩn thận hơn trong mã.
===
Tôi nghĩ rằng JavaDoc thực hiện tốt việc mô tả sự khác biệt giữa Lock
và synchronized
(sự nhấn mạnh là của tôi):
Việc triển khai khóa cung cấp các hoạt động khóa mở rộng hơn mức có thể thu được bằng cách sử dụng các phương thức và câu lệnh được đồng bộ hóa. Chúng cho phép cấu trúc linh hoạt hơn , có thể có các thuộc tính khá khác nhau và có thể hỗ trợ nhiều đối tượng Điều kiện liên quan .
...
Việc sử dụng phương pháp đồng bộ hoặc báo cáo cung cấp quyền truy cập vào các khóa màn ngầm kết hợp với mọi đối tượng, nhưng lực lượng tất cả mua lại khóa và phát hành để xảy ra một cách khối cấu trúc : khi nhiều ổ khóa được mua họ phải được phát hành theo thứ tự ngược lại , và tất cả các khóa phải được phát hành trong cùng một phạm vi từ vựng mà chúng đã được mua .
Mặc dù cơ chế phạm vi cho các phương thức và câu lệnh được đồng bộ hóa giúp lập trình với khóa màn hình dễ dàng hơn nhiều và giúp tránh nhiều lỗi lập trình phổ biến liên quan đến khóa, có những lúc bạn cần làm việc với khóa theo cách linh hoạt hơn. Ví dụ: * * một số thuật toán * để truyền tải các cấu trúc dữ liệu được truy cập đồng thời yêu cầu sử dụng "bàn giao tay" hoặc "khóa chuỗi" : bạn có được khóa của nút A, sau đó nút B, sau đó giải phóng A và thu được C, sau đó giải phóng B và thu nhận D và cứ thế. Việc triển khai giao diện Khóa cho phép sử dụng các kỹ thuật như vậy bằng cách cho phép khóa và được phát hành trong các phạm vi khác nhau vàcho phép nhiều khóa được mua và phát hành theo bất kỳ thứ tự nào .
Với sự linh hoạt tăng lên này có thêm trách nhiệm . Việc không có khóa có cấu trúc khối sẽ loại bỏ việc giải phóng khóa tự động xảy ra với các phương thức và câu lệnh được đồng bộ hóa. Trong hầu hết các trường hợp, nên sử dụng thành ngữ sau:
...
Khi khóa và mở khóa xảy ra ở các phạm vi khác nhau , phải cẩn thận để đảm bảo rằng tất cả mã được thực thi trong khi khóa được giữ được bảo vệ bằng cách thử cuối cùng hoặc thử bắt để đảm bảo rằng khóa được giải phóng khi cần thiết.
Việc triển khai khóa cung cấp chức năng bổ sung cho việc sử dụng các phương thức và câu lệnh được đồng bộ hóa bằng cách cung cấp một nỗ lực không chặn để có được khóa (tryLock ()), một nỗ lực để có được khóa có thể bị gián đoạn (lockInterruptingly () và cố gắng có được khóa có thể hết thời gian (tryLock (dài, TimeUnit)).
...