2009-12-23 27 views
21

Tôi đã học được rằng tôi nên mở khóa thứ tự ngược lại để khóa thứ tự. Ví dụ.Bạn có giải thích việc đặt hàng khóa không?

A.lock(); 
B.lock(); 
B.unlock(); 
A.unlock(); 

Nhưng, những gì xảy ra nếu tôi làm như thế này:

A.lock(); 
B.lock(); 
A.unlock(); 
B.unlock(); 

tôi cố gắng để thực hiện một kịch bản bế tắc, nhưng nếu tôi luôn luôn khóa Một sớm sau đó B, sau đó tôi không biết làm thế nào bế tắc sẽ xảy ra. Bạn có giúp tôi không?

+0

Bạn đang nói về một trường hợp có nhiều quy trình giữ khóa hoặc bạn chỉ xử lý một quy trình đơn lẻ? –

+0

nhiều quy trình, tất nhiên. –

+4

Không phải "tất nhiên", tại sao lại có nhiều quy trình? Chỉ áp dụng tốt cho các chuỗi trong một quy trình. – djna

Trả lời

19

Đặt hàng khóa chỉ có nghĩa là bạn ngăn chặn deadlocks bằng cách lấy khóa theo thứ tự cố định và không lấy lại khóa sau khi bạn bắt đầu mở khóa.

Tôi không nghĩ rằng thứ tự mở khóa làm cho bất kỳ sự khác biệt ở đây (trong thực tế, nó phải là có lợi cho phát hành một khóa càng sớm càng tốt, ngay cả khi ra khỏi trật tự)

9

dụ của bạn sẽ không bế tắc với chính nó bao giờ hết. Mở khóa theo thứ tự ngược lại không quan trọng, nó khóa theo thứ tự nhất quán. Điều này sẽ khóa chết, mặc dù mở khóa theo thứ tự ngược lại

Thread 1 

A.lock(); 
B.lock(); 
B.unlock(); 
A.unlock(); 

Thread 2 

B.lock(); 
A.lock(); 
A.unlock(); 
B.unlock(); 
2

Tôi không nghĩ rằng bế tắc sẽ xảy ra ở đây. Khái niệm bế tắc chung là một luồng chờ một số tài nguyên bị khóa bởi luồng khác, trong khi luồng khác cần tài nguyên bị khóa bởi chuỗi đầu tiên để hoàn thành và giải phóng tài nguyên cần thiết trước tiên.

Further reading

1

Trình tự mở khóa sẽ không ảnh hưởng như thế nào dễ bị hệ thống của bạn là bế tắc, tuy nhiên có một lý do để suy nghĩ về thứ tự của unlock:

Để tránh deadlocks bạn phải làm chắc chắn rằng khóa/mở khóa của bạn được ghép nối, trong đó bạn không bao giờ bỏ lỡ một mở khóa. Như một cách tiếp cận phong cách, bằng cách rõ ràng có khối mã có trách nhiệm cho một khóa particualr nó dễ dàng hơn nhiều để nhận dạng trực quan mà khóa và mở khóa được ghép nối. Hiệu ứng cuối cùng là mã chính xác rõ ràng có thể sẽ lấy và giải phóng ổ khóa khi bạn mô tả.

32

Trong trường hợp đơn giản nhất định, mở khóa theo thứ tự ngược lại là không cần thiết để tránh bế tắc.

Tuy nhiên, vì mã trở nên phức tạp hơn, mở khóa theo thứ tự ngược lại giúp bạn duy trì thứ tự khóa thích hợp.

xem xét:

A.lock(); 
B.lock(); 
Foo(); 
A.unlock(); 
Bar(); 
B.unlock(); 

Nếu Bar() nỗ lực để reacquire A, bạn đã có hiệu quả phá vỡ trật tự khóa của bạn. Bạn đang giữ B và sau đó cố gắng để có được A. Bây giờ nó có thể bế tắc.

Nếu bạn mở khóa theo phong cách trái ngược nhau (mà là rất tự nhiên nếu bạn sử dụng RAII):

A.lock(); 
B.lock(); 
Foo(); 
B.unlock(); 
Bar(); 
A.unlock(); 

sau đó nó không quan trọng nếu Bar() nỗ lực để có một khóa, như khóa đặt hàng sẽ được bảo tồn .

+1

Đây là câu trả lời đúng _the_ IMO: nếu bạn chấp nhận quy tắc lấy khóa theo cùng thứ tự trong toàn bộ hệ thống của bạn ở các cấp độ khác nhau (bên trong các hàm vv) và không 't phát hành theo thứ tự ngược lại sau đó kịch bản từ câu trả lời của Adrian dẫn đến một khả năng bế tắc. Tôi muốn điều này "** có thể bế tắc **" là một chút có thể nhìn thấy được bên dưới đối số "phong cách tốt" (mà tôi hoàn toàn đồng ý với là tốt). – starikoff

+0

Không chỉ là câu trả lời đúng, nó chỉ ra rằng tất cả các câu trả lời tuyên bố rằng lệnh mở khóa là không liên quan đến bế tắc là sai. –

+0

Vâng, vấn đề đó chỉ xảy ra nếu bạn mua lại ổ khóa mà bạn đã phát hành trước đó (mà không cần phải phát hành ổ khóa "sau"). Câu trả lời được cho là sai của tôi xác định thứ tự khóa là "lấy khóa theo thứ tự cố định và không lấy lại khóa sau khi bạn bắt đầu mở khóa". – Thilo

0

Và đối với Java, mở khóa theo thứ tự ngược lại nếu synchronized từ khóa được sử dụng để khóa. Không có cách nào để mở khóa theo thứ tự khác để sử dụng từ khóa synchronized.

synchronized(a) { 
    synchronized(b) { 
    // statements 
    } 
} 
+2

Tôi muốn thể hiện rằng tôi không đồng ý với những nhược điểm về câu trả lời này. Rõ ràng đây không phải là câu hỏi phức tạp nhất về câu hỏi này, nó cho thấy một quan điểm khác, có lẽ giúp hiểu được vấn đề –

0
 > lock(B)                                                 
     > ---------- lock(C) 
     > ---------- lock(B) >>>> would block here 
     > ---------- release(B) 
     > ---------- release(C) 
     > lock(C)  >>>>>> would block here 
     > release(B) 
     > release(C) 

câu trả lời của họ là rất tốt, đây là một tình huống bế tắc có thể xảy ra nếu không có thứ tự khóa & phát hành được thực hiện. Một từ, Phát hành không theo thứ tự & khóa phá vỡ giả định mà chúng tôi đã sử dụng để thiết kế quản lý tài nguyên được chia sẻ và vùng quan trọng của chúng tôi.

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