34

Sự khác biệt giữa phương thức được đồng bộ hóa và khối được đồng bộ hóa trong Java là gì?Sự khác nhau giữa phương thức được đồng bộ hóa và khối đồng bộ trong Java là gì?

Tôi đã được tìm kiếm câu trả lời trên mạng, mọi người dường như để được như vậy chắc chắn về một :-(này

mất của tôi sẽ không có sự khác biệt giữa hai, ngoại trừ khối đồng bộ có thể hơn cục bộ trong phạm vi và do đó khóa sẽ có thời gian ít hơn ??

và trong trường hợp của lock trên một phương pháp tĩnh, về những gì là Khóa lấy? ý nghĩa của một lock trên lớp là gì?

+0

@ try-catch-cuối cùng Đó không phải là một bản sao của câu hỏi này; câu hỏi đó hỏi liệu một phương thức đồng bộ có cung cấp quyền truy cập độc quyền vào phương thức duy nhất hay cho toàn bộ đối tượng hay không. –

+0

@MarkRotteveel Bạn nói đúng về các tiêu đề khác nhau. Mặt khác, các câu trả lời của câu hỏi khác cũng đề cập đến sự khác biệt: điều chỉnh phần đồng bộ hóa với một số câu lệnh (hoặc không) và kiểm soát nơi khóa (hoặc không kiểm soát được). –

Trả lời

44

Phương pháp đồng bộ sử dụng trình nhận phương thức làm khóa (tức là this cho các phương thức không tĩnh và lớp kèm theo cho các phương thức tĩnh). Synchronized khối sử dụng biểu thức dưới dạng khóa.

Vì vậy, trong hai phương pháp sau đây là tương đương từ khóa tiềm năng:

synchronized void mymethod() { ... } 

void mymethod() { 
    synchronized (this) { ... } 
} 

Đối với phương pháp tĩnh, lớp sẽ bị khóa:

class MyClass { 
    synchronized static mystatic() { ... } 

    static mystaticeq() { 
    syncrhonized (MyClass.class) { ... } 
    } 
} 

Đối với khối đồng bộ, bạn có thể sử dụng bất kỳ phi null đối tượng dưới dạng khóa:

synchronized (mymap) { 
    mymap.put(..., ...); 
} 

Phạm vi khóa

Đối với phương pháp đồng bộ, khóa sẽ được giữ trong phạm vi phương thức, trong khi ở khối synchronized, khóa chỉ được giữ trong phạm vi khối đó (còn được gọi là phần quan trọng). Trong thực tế, JVM được phép tối ưu hóa bằng cách loại bỏ một số hoạt động ra khỏi việc thực thi khối synchronized nếu nó có thể chứng minh rằng nó có thể được thực hiện một cách an toàn.

+0

Tôi đọc một số thời gian trước đây (mất nguồn) mà đồng bộ hóa trên phương pháp có thể dễ dàng hơn để tối ưu hóa nội bộ bằng JVM hơn đồng bộ hóa trên khối ngay cả khi khối đó đóng gói toàn bộ thân phương thức. Có thể là điểm chuẩn vi mô thú vị để thử. –

+1

Trong phạm vi khóa, bạn có thể có nghĩa là "... trong khối đồng bộ, khóa chỉ được giữ trong khối đồng bộ" và không "... trong khi phương pháp đồng bộ, khóa chỉ được giữ trong khối đồng bộ" – mrvincenzo

+2

@Gregory Mostizky Theo bài viết này, JVM tạo ra bytecode ít hơn cho một phương thức được đồng bộ khi so sánh với một khối được đồng bộ hóa. http://www.ibm.com/developerworks/java/library/j-5things15/index.html?ca=drs- –

3

có , đó là một sự khác biệt, khác là bạn có thể có được một khóa trên các đối tượng khác hơn this.

8

Phương thức được đồng bộ hóa là viết tắt. Đây:

class Something { 
    public synchronized void doSomething() { 
     ... 
    } 

    public static synchronized void doSomethingStatic() { 
     ... 
    } 
} 

là, đối với tất cả các tính năng, tương đương với điều này:

class Something { 
    public void doSomething() { 
     synchronized(this) { 
      ... 
     } 
    } 

    public static void doSomethingStatic() { 
     synchronized(Something.class) { 
      ... 
     } 
    } 
} 

(. Trong trường hợp Something.class là đối tượng lớp cho lớp Something)

Vì vậy, trên thực tế, với một khối được đồng bộ hóa, bạn có thể cụ thể hơn về khóa của mình và chi tiết hơn về thời điểm bạn muốn sử dụng, nhưng khác với điều đó không có sự khác biệt.

0

Một đồng bộ phương pháp khóa trên trường hợp đối tượng phương pháp này được chứa trong

Trong trường hợp như một khối đồng bộ có thể khóa vào bất kỳ đối tượng -. Thường là một obect mutex được định nghĩa như là một biến ví dụ. Điều này cho phép kiểm soát nhiều hơn những gì các khóa đang hoạt động.

2

Sự khác biệt chính là: nếu bạn khai báo phương thức được đồng bộ, thì toàn bộ phần thân của phương thức sẽ được đồng bộ hóa; nếu bạn sử dụng khối đồng bộ, tuy nhiên, sau đó bạn có thể bao quanh chỉ là "phần quan trọng" của phương thức trong khối được đồng bộ hóa, trong khi để phần còn lại của phương thức ra khỏi khối.

Nếu toàn bộ phương pháp là một phần của phần quan trọng, thì có hiệu quả là không có sự khác biệt. Nếu đó không phải là trường hợp, sau đó bạn nên sử dụng một khối đồng bộ xung quanh chỉ là phần quan trọng. Càng có nhiều câu lệnh bạn có trong một khối được đồng bộ hóa, thì tính song song tổng thể mà bạn nhận được ít hơn, vì vậy bạn muốn giữ chúng ở mức tối thiểu.

+0

Theo dõi nhanh: Điều đó có nghĩa là khối được đồng bộ hóa ít tốn kém hơn để sử dụng hơn phương pháp được đồng bộ hóa ? – Everyone

+0

Nếu khối đồng bộ bao gồm tất cả nội dung của hàm, thì không có sự khác biệt. Tuy nhiên, nếu bạn sử dụng một khối đồng bộ, bạn có thể bao quanh phần quan trọng (có lẽ để lại một số tính toán ra khỏi vùng được đồng bộ hóa). Nếu bạn làm điều đó, chương trình của bạn sẽ chạy nhanh hơn. –

0

Việc lấy của tôi sẽ không có sự khác biệt giữa hai, ngoại trừ khối đồng bộ có thể được bản địa hóa hơn trong phạm vi và do đó khóa sẽ có thời gian ít hơn ??

Có. Bạn đúng rồi. Không giống như phương thức synchronized, các câu lệnh đồng bộ phải chỉ định đối tượng cung cấp khóa nội tại.

Ví dụ từ java hướng dẫn:

public void addName(String name) { 
    synchronized(this) { 
     lastName = name; 
     nameCount++; 
    } 
    nameList.add(name); 
} 

báo cáo đồng bộ cũng hữu ích cho việc cải thiện đồng thời với đồng bộ hóa hạt mịn. Bạn có thể tìm thấy ví dụ tốt trên cùng một trang hướng dẫn cho trường hợp sử dụng bên dưới.

Giả sử, ví dụ: lớp MsLunch có hai trường mẫu, c1 và c2, không bao giờ được sử dụng cùng nhau. Tất cả các bản cập nhật của các trường này phải là synchronized, nhưng không có lý do gì để ngăn cập nhật c1 bị xen kẽ với bản cập nhật c2 - và làm như vậy sẽ giảm đồng thời bằng cách tạo chặn không cần thiết. Thay vì sử dụng các phương pháp đã đồng bộ hóa hoặc bằng cách khác, sử dụng khóa liên kết với điều này, chúng tôi chỉ tạo hai đối tượng để cung cấp khóa.

Và trong trường hợp Khóa trên phương pháp tĩnh, Khóa được lấy là gì? Ý nghĩa của Khóa trên Lớp là gì?

Trong trường hợp này, chuỗi sẽ lấy khóa nội tại cho đối tượng Lớp được liên kết với lớp. Do đó việc truy cập vào các trường tĩnh của lớp được điều khiển bởi một khóa khác với khóa cho bất kỳ cá thể nào của lớp.

Khi bạn thực hiện một phương pháp như synchronized (không static):

Nó không phải là có thể cho hai lời gọi của synchronized phương pháp 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.

Nếu bạn thực hiện một phương pháp như static synchronized:

Nó không phải là có thể cho hai lời gọi của static synchronized phương pháp trên các đối tượng khác nhau của cùng một lớp để interleave. Khi một luồng đang thực hiện phương thức static synchronized cho đối tượng lớp A, tất cả các luồng khác gọi phương thức static synchronized trên bất kỳ đối tượng nào của khối lớp A (tạm ngừng thực thi) cho đến khi chuỗi đầu tiên được thực hiện với phương thức thực hiện.

Bạn tìm thấy lựa chọn thay thế tốt hơn để đồng bộ hóa trong câu hỏi SE này:

Avoid synchronized(this) in Java?

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