2013-05-26 36 views
12

Đây là một mô hình được khuyến khích rằng wait() nên được gọi bên trong một vòng lặp while bên trong một khối được đồng bộ hóa.Làm thế nào để wait() lấy lại Khóa trong Java

Câu hỏi của tôi là cách chuỗi chờ() lấy lại khóa?

// Thread 1 
    synchronized (mon) { 
    while (!condition) 
      mon.wait(); 

    // Do something 
    } 

//Thread 2 
    synchronized (mon) {//set condition appropriately 
      mon.notify(); 
    } 

Cân nhắc chuỗi 1 chạy trước và bắt đầu chờ điều kiện. Nó phát hành khóa và thread 2 có được khóa thiết lập điều kiện và thông báo thread 1. Bây giờ thread 1 được khóa, kiểm tra điều kiện và bắt đầu thực hiện "làm điều gì đó".

Câu hỏi của tôi là khi Chủ đề 1 được thông báo nó bắt đầu thực hiện từ điều kiện trong khi dòng mã đã đồng bộ hóa (mon) không bao giờ được thực hiện lại thì luồng 1 có khóa như thế nào? Động lực bên trong cung cấp khóa cho Chủ đề 1 là gì?

Trả lời

7

Khi thread1 được thông báo các chủ đề đã được khóa trước khi nó có thể thoát khỏi phương pháp chờ đợi, xem doc java cho Object # chờ đợi:

Các chủ đề T được lấy ra từ tập chờ này đối tượng và được bật lại để lập lịch trình chuỗi. Sau đó, nó cạnh tranh theo cách thông thường với các luồng khác để có quyền đồng bộ hóa trên đối tượng ; một khi nó đã giành được quyền kiểm soát đối tượng, tất cả các yêu cầu đồng bộ hóa của đối tượng đó sẽ được khôi phục về trạng thái ante - tức là, đến thời điểm mà phương thức wait được gọi. Chủ đề T sau đó trả về từ yêu cầu của phương thức wait. Do đó, khi trả về từ phương thức wait, trạng thái đồng bộ của đối tượng và của chủ đề T chính xác như khi phương pháp wait được gọi là được gọi.

+0

+1 cho đoạn trích javadoc. –

+0

@Nathan: Tôi nghĩ chúng ta biết câu trả lời :-) Chúng tôi không (ít nhất là tôi không hiểu) phần này của Tài liệu Java: Vì vậy, khi trở về từ phương thức * {@code wait}, đồng bộ hóa trạng thái của đối tượng và của * chuỗi {@code T} chính xác như khi phương thức {@code wait} * được gọi. – Geek

+0

@Geek: bạn không hiểu gì? thoát khỏi phương thức chờ đặt chuỗi trong một khối được đồng bộ hóa, vì vậy nó cần lấy khóa trước. nếu không nó sẽ được thực hiện mã trong một khối đồng bộ mà không cần phải có được khóa. –

7

synchronized(mon) không phải là biểu thức phải được thực hiện. Đó là một yếu tố cú pháp trong mã nguồn cho trình biên dịch (và sau đó là thời gian chạy) mà phần được bao bọc của mã phải chỉ được thực hiện sau khi khóa liên quan với mon đã được chủ đề hiện tại thu được, ngay cả khi bạn không "đến từ" dòng mã trước khối đồng bộ.

wait() giải phóng khóa và phải phản hồi lại trước khi trở về.

+0

Câu trả lời của bạn là hoàn toàn chính xác. Bạn có thể cho tôi biết thông tin siêu dữ liệu này hoạt động như thế nào trong thời gian chạy không. Bạn có thể vui lòng chỉ cho tôi một số tài nguyên mà tôi có thể đọc về nó không. – Geek

+0

Tôi đoán bạn có thể tìm thấy những gì bạn đang tìm kiếm trong [Đặc điểm kỹ thuật JVM] (http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.11.10), nhưng tôi chưa bao giờ đọc chúng. –

+1

Chờ cuộc gọi thông báo cho JVM rằng chuỗi có được khóa muốn từ bỏ nó. JVM của nó đặt chuỗi trong hàng đợi chờ và giải phóng khóa. Khi thông báo (tất cả) được gọi thì tín hiệu được gửi đến JVM mà luồng đã nhận khóa (có thông báo (tất cả) đã được gọi) đã phát hành khóa và bất kỳ ứng cử viên đủ điều kiện nào (có trong hàng đợi chờ do JVM đặt) được JVM chọn để lấy khóa. Xem liên kết này để hiểu luồng kiểm soát http://booxs.biz/images/java/thread-states.png – Saurabh

0

Sau khi Thread 1 được thông báo, nó đã khóa ngay lập tức và bắt đầu chạy // Làm điều gì đó.

Khi Chủ đề 1 chờ, nó chỉ nhả khóa tạm thời và khi chuỗi được thông báo, nó có thể lấy lại khóa và không cần chạy đồng bộ (...).

0
// Thread 1 
synchronized (mon) { 
Systemout.println("I am invoked!"); 
while (!condition) 
     mon.wait(); 

// Do something 
} 

//Thread 2 
synchronized (mon) {//set condition appropriately 
     mon.notify(); 
} 

Trong trường hợp ban đầu: Cân nhắc chuỗi 1 chạy trước và bắt đầu chờ điều kiện. Nó phát hành khóa và thread 2 có được khóa thiết lập điều kiện và thông báo thread 1. Bây giờ thread 1 được khóa, kiểm tra điều kiện và bắt đầu thực hiện "làm điều gì đó".

Nếu tôi hiểu được một cách chính xác sau:

Sợi T sau đó được lấy ra từ tập chờ đợi cho đối tượng này và kích hoạt lại cho lịch chủ đề. Sau đó nó cạnh tranh theo cách thông thường với các luồng khác để có quyền đồng bộ hóa trên đối tượng; một khi nó đã giành được quyền kiểm soát đối tượng, tất cả các yêu cầu đồng bộ hóa của nó trên đối tượng sẽ được khôi phục về trạng thái ante - tức là, với tình huống khi thời gian chờ đợi được gọi. T sau đó trả về từ lời gọi phương thức chờ. Do đó, khi trả về từ phương thức chờ, trạng thái đồng bộ của đối tượng và chuỗi T là chính xác như khi phương thức chờ được gọi.

dòng Systemout.println ("Tôi được gọi!"); sẽ không được thực thi, vì "Như vậy, khi trả về từ phương thức chờ, trạng thái đồng bộ của đối tượng và chuỗi T chính xác như khi phương thức chờ được gọi."

Tôi có đúng không?

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