2011-08-02 38 views
27

thể trùng lặp:
Java SynchronizationĐồng bộ hóa()/wait()/notifyAll() làm gì trong Java?

Tôi đang đọc cuốn sách Beginning Android Games.

Nó sử dụng synchronized() rất nhiều nhưng tôi thực sự không hiểu nó làm gì. Tôi đã không sử dụng Java trong một thời gian dài và tôi không chắc chắn nếu tôi đã từng sử dụng đa luồng.

Trong ví dụ Canvas, nó sử dụng synchronized(this). Tuy nhiên trong ví dụ OpenGL ES, nó tạo ra một đối tượng được gọi là stateChanged và sau đó sử dụng synchronized(stateChanged). Khi trạng thái trò chơi thay đổi nó gọi stateChanged.wait() và sau đó stateChanged.notifyAll();

Một số mã:

Object stateChanged = new Object(); 

    //The onPause() looks like this: 
    public void onPause() 
     { 
      synchronized(stateChanged) 
      { 
       if(isFinishing()) 
        state = GLGameState.Finished; 
       else 
        state = GLGameState.Paused; 

       while(true) 
       { 
        try 
        { 
         stateChanged.wait(); 
         break; 
        } catch(InterruptedException e) 
        { 
        } 
       } 
      } 
     } 
//The onDrawSurface looks like this: 
public void onDrawFrame(GL10 gl) 
    { 
     GLGameState state = null; 
     synchronized(stateChanged) 
     { 
      state = this.state; 
     } 

     if(state == GLGameState.Running) 
     { 

     } 

     if(state == GLGameState.Paused) 
     { 
      synchronized(stateChanged) 
      { 
       this.state = GLGameState.Idle; 
       stateChanged.notifyAll(); 
      } 
     } 

     if(state == GLGameState.Finished) 
     { 
      synchronized(stateChanged) 
      { 
       this.state = GLGameState.Idle; 
       stateChanged.notifyAll(); 
      } 
     } 
    } 

//the onResume() looks like this: 
synchronized(stateChanged) 
     { 
      state = GLGameState.Running; 
      startTime = System.nanoTime(); 
     } 
+4

(Nghiêm túc) bạn có tìm kiếm gì ở bất cứ nơi nào trước khi hỏi điều này không? Thậm chí tìm kiếm Stack Overflow? –

+1

Vâng, tôi đã làm ... @Joachim Sauver câu hỏi không bao gồm chờ đợi()/thông báo() –

+0

Bạn chỉ cần thêm wait()/notify() - bạn nên cố gắng tạo câu hỏi đúng lần đầu tiên thay vì xây dựng nó trực tiếp. –

Trả lời

29

This Java Tutorial có lẽ có thể giúp bạn hiểu những gì sử dụng đồng bộ hóa trên một đối tượng.

Khi object.wait() được gọi là nó sẽ giải phóng khóa được giữ trên đối tượng đó (điều này xảy ra khi bạn nói synchronized(object)) và cố định chuỗi. Chuỗi sau đó đợi cho đến khi object.notify() hoặc object.notifyAll() được gọi bằng một chuỗi riêng biệt. Khi một trong các cuộc gọi này xảy ra, nó sẽ cho phép bất kỳ chủ đề nào bị dừng do object.wait() để tiếp tục. Điều này làm không có nghĩa là luồng được gọi là object.notify() hoặc object.notifyAll() sẽ đóng băng và chuyển quyền kiểm soát đến chuỗi chờ, điều đó có nghĩa là các chủ đề chờ này hiện có thể tiếp tục, trong khi trước khi chúng không tồn tại.

+0

Điều đó có ý nghĩa ... do đó, sử dụng wait() nó dừng thread chính sẽ tạm dừng ứng dụng và làm cho Điểm dừng OpenGL ES. Sau đó, sau khi OpenGL ES dừng lại, chuỗi trình kết xuất gọi notifyAll() làm cho kết thúc chủ đề chính tạm dừng ứng dụng –

1

chỉ một thread có thể hoạt động và bên trong khối đồng bộ bởi đối tượng nhất định. dừng cuộc gọi chờ từ bỏ quyền này và hủy kích hoạt chuỗi hiện tại cho đến khi ai đó gọi đến (tất cả)() Sau đó, chuỗi không hoạt động bắt đầu muốn chạy lại trong khối được đồng bộ hóa, nhưng được xử lý bằng tất cả các chủ đề khác muốn. Chỉ có một cách nào đó được lựa chọn (lập trình viên không thể ảnh hưởng hay không phụ thuộc vào cái nào) thực tế có được ở đó.

4

Java (dựa trên Android) có thể chạy dưới nhiều luồng có thể sử dụng nhiều lõi CPU. Đa luồng có nghĩa là bạn có thể có Java thực hiện hai quy trình tại cùng một thời điểm. Nếu bạn có một khối mã hoặc phương thức mà bạn cần đảm bảo chỉ có thể được vận hành bởi một luồng tại một thời điểm, bạn đồng bộ hóa khối mã đó.

Here is the official Java explanation from Oracle

Điều quan trọng là phải biết rằng có một chi phí xử lý/io liên quan đến bằng cách sử dụng đồng bộ và bạn chỉ muốn sử dụng nó khi bạn cần nó. Điều quan trọng là nghiên cứu các lớp/phương thức Java là luồng an toàn. Ví dụ, toán tử tăng ++ không phải là guarateed là thread an toàn, trong khi bạn có thể dễ dàng tạo một khối mã đồng bộ tăng giá trị sử dụng + = 1.

44

Từ khóa synchronized được sử dụng để giữ biến hoặc phương thức - an toàn. Nếu bạn quấn một biến trong một khối đồng bộ như vậy:

synchronized(myVar) { 
    // Logic involing myVar 
} 

Sau đó, bất kỳ nỗ lực để thay đổi giá trị của myVar từ thread khác trong khi logic bên trong khối đồng bộ đang chạy sẽ đợi cho đến khi khối đã hoàn thành thi công. Nó đảm bảo rằng giá trị đi vào khối sẽ giống nhau thông qua vòng đời của khối đó.

+0

Có đúng không khi nói rằng phiên bản Java này của một Mutex? – Siavash

+1

@Siavash From .NET? Vâng. –

1

Từ khóa được đồng bộ hóa trong java được sử dụng cho 2 mục.

Ý nghĩa đầu tiên được gọi là phần quan trọng, tức là một phần của mã có thể được truy cập bởi một chuỗi cùng một lúc. Đối tượng bạn chuyển đến synchronized cho phép một số loại đặt tên: nếu một mã được chạy trong synchronized(a), nó không thể truy cập vào khối khác vào synchronized(a) nhưng có thể truy cập vào khối mã vào synchronized(b).

Sự cố khác là liên lạc giữa các luồng.Chủ đề có thể đợi cho đến khi luồng khác thông báo cho nó. Cả hai chờ đợi và thông báo phải được viết vào khối synchronized.

Đó là một mô tả rất ngắn. Tôi muốn đề nghị bạn tìm kiếm một số hướng dẫn về đa luồng và đọc nó.

10

Khi được sử dụng như thế này:

private synchronized void someMehtod() 

Bạn nhận được những hiệu ứng:

1. Thứ nhất, nó không phải là có thể cho hai lời gọi của phương pháp đồng bộ trên cùng một đối tượng để interleave. Khi một luồng đang thực hiện một phương thức đồng bộ cho một đối tượng, tất cả các luồng khác gọi ra các phương thức đồng bộ cho cùng một khối đối tượng (tạm dừng thực hiện) cho đến khi luồng đầu tiên được thực hiện với đối tượng.

2. Thứ hai, khi một phương thức đồng bộ thoát, nó sẽ tự động thiết lập mối quan hệ xảy ra trước đó với bất kỳ lời gọi tiếp theo nào của phương thức được đồng bộ hóa cho cùng một đối tượng. Điều này đảm bảo rằng các thay đổi đối với trạng thái của đối tượng được hiển thị cho tất cả các luồng.

(Trích từ here)

Bạn nhận được một hiệu ứng tương tự khi bạn sử dụng một khối đồng bộ mã:

private void someMethod() { 
    // some actions... 

    synchronized(this) { 
    // code here has synchronized access 
    } 

    // more actions... 
} 

Như đã giải thích here

+0

Ok. Còn các phương thức wait() và notify() thì sao? Làm thế nào để họ can thiệp vào các chủ đề ... (Tôi đã thêm một số mã của tôi vào câu hỏi ban đầu) –

0

Từ khóa được đồng bộ hóa, cùng với hoạt động chờ và thông báo tạo thành một nonblocking condition monitor, một cấu trúc hữu ích để điều phối nhiều luồng.

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