Khối đồng bộ hóa Java cho .class


102

Mã java này có nghĩa là gì? Nó sẽ đạt được khóa trên tất cả các đối tượng của MyClass?

synchronized(MyClass.class) {
   //is all objects of MyClass are thread-safe now ??
}

Và mã trên khác với mã này như thế nào:

synchronized(this) {
   //is all objects of MyClass are thread-safe now ??
}

Câu trả lời:


144

Đoạn mã synchronized(X.class)sử dụng cá thể lớp làm màn hình. Vì chỉ có một cá thể lớp (đối tượng đại diện cho siêu dữ liệu lớp trong thời gian chạy) nên một luồng có thể nằm trong khối này.

Với synchronized(this)khối được bảo vệ bởi phiên bản. Đối với mọi trường hợp, chỉ một luồng có thể đi vào khối.

synchronized(X.class)được sử dụng để đảm bảo rằng có chính xác một Chủ đề trong khối. synchronized(this)đảm bảo rằng có chính xác một luồng cho mỗi phiên bản. Nếu điều này làm cho mã thực sự trong chuỗi khối an toàn phụ thuộc vào việc triển khai. Nếu đột biến chỉ trạng thái của cá thể synchronized(this)là đủ.


6
"as nhiều thread có thể nhập vào khối vì có trường hợp" ngụ ý rằng dạng thứ hai hoạt động như một semaphore không đúng. Bạn nên nói điều gì đó như: "sync (this) đảm bảo rằng chỉ một luồng có thể nhập khối cho một phiên bản nhất định của lớp".
liwp

Đã sửa. Tôi đã định nói điều đó.
Thomas Jung,

2
cá thể lớp so với cá thể là gì?
Weishi Zeng

Vì vậy, nếu bạn có một phương thức tĩnh và chúng tôi không muốn đồng bộ hóa tất cả phần thân của nó, thì chúng tôi đồng bộ hóa (điều này) là không tốt, thay vào đó đồng bộ hóa (Foo.class) là phù hợp. Có đúng không?
krupal.agile

84

Để thêm vào các câu trả lời khác:

static void myMethod() {
  synchronized(MyClass.class) {
    //code
  }
}

tương đương với

static synchronized void myMethod() {
  //code
}

void myMethod() {
  synchronized(this) {
    //code
  }
}

tương đương với

synchronized void myMethod() {
  //code
}

12
Tôi mất lần đọc thứ hai để nhận ra rằng hai ví dụ đầu tiên có từ khóa "static". Chỉ chỉ ra điều đó cho những người khác có thể đã nhìn thấy điều này và bỏ lỡ nó. Nếu không có từ khóa static, hai ví dụ đầu tiên sẽ không giống nhau.
kurtzbot

1
Những ví dụ đó KHÔNG tương đương! Các phương thức được đồng bộ hóa được "đồng bộ hóa" như một lỗ hổng khi một luồng cố gắng gọi các phương thức. Mặt khác, các khối có thể có mã bên trên và bên dưới chúng, có thể được thực thi từ nhiều luồng. Chúng chỉ đồng bộ hóa trong khối! Điều đó không giống nhau!
JacksOnF1re

public static Singleton getInstance () {if (instance == null) {sync (Singleton.class) {instance = new Singleton (); }} trả về thể hiện; }
JacksOnF1re

2
Toàn bộ vấn đề là có không có mã ngoài synchronizedkhối. Điều đó làm cho chúng tương đương nhau. Nếu bạn thay đổi một ví dụ, chúng thực sự không còn giống nhau nữa.
Jorn

22

Không, đầu tiên sẽ có một khóa về định nghĩa lớp MyClass, không phải tất cả các trường hợp của nó. Tuy nhiên, nếu được sử dụng trong một trường hợp, điều này sẽ chặn tất cả các trường hợp khác một cách hiệu quả, vì chúng chia sẻ một định nghĩa lớp duy nhất.

Cái thứ hai sẽ chỉ nhận được một khóa trên phiên bản hiện tại.

Về việc liệu điều này có làm cho các đối tượng của bạn an toàn hay không, đó là một câu hỏi phức tạp hơn nhiều - chúng tôi cần xem mã của bạn!


1
vâng, MyClass.class có thể là bất kỳ biến tĩnh nào và có cùng tác dụng.
pstanton
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.