Câu trả lời:
Vì một phương thức tĩnh không có đối tượng liên quan, nên khóa từ khóa được đồng bộ hóa trên lớp, thay vì đối tượng?
Đúng. :)
this
là khóa có được trên các phương thức ví dụ-, vui lòng sửa nó thành Oscar.
Chỉ cần thêm một chút chi tiết vào câu trả lời của Oscar (rất ngắn gọn!), Phần có liên quan trên Đặc tả ngôn ngữ Java là 8.4.3.6, 'Phương thức được đồng bộ hóa' :
Một phương thức được đồng bộ hóa có được một màn hình ( §17.1 ) trước khi nó thực thi. Đối với phương thức lớp (tĩnh), trình giám sát được liên kết với đối tượng Lớp cho lớp của phương thức được sử dụng. Đối với một phương thức cá thể, trình giám sát được liên kết với điều này (đối tượng mà phương thức được gọi) được sử dụng.
Một điểm bạn phải cẩn thận (một số lập trình viên thường rơi vào cái bẫy đó) là không có liên kết giữa các phương thức tĩnh được đồng bộ hóa và các phương thức không tĩnh được đồng bộ hóa, tức là:
class A {
static synchronized f() {...}
synchronized g() {...}
}
Chủ yếu:
A a = new A();
Chủ đề 1:
A.f();
Chủ đề 2:
a.g();
f () và g () không được đồng bộ hóa với nhau và do đó có thể thực hiện hoàn toàn đồng thời.
synchronized (MyClass.class) {...}
.
Trừ khi bạn thực hiện g () như sau:
g() {
synchronized(getClass()) {
...
}
}
Tôi thấy mẫu này cũng hữu ích khi tôi muốn thực hiện loại trừ lẫn nhau giữa các phiên bản khác nhau của đối tượng (ví dụ cần thiết khi tích lũy tài nguyên bên ngoài).
getClass()
trả về kiểu thời gian chạy ; nếu bạn phân lớp lớp, thì lớp cha và lớp con sẽ đồng bộ hóa trên các khóa khác nhau. synchronized(MyClass.class)
là cách để đi nếu bạn cần đảm bảo tất cả các trường hợp sử dụng cùng một khóa.
Hãy xem trang tài liệu oracle về Khóa và đồng bộ hóa
Bạn có thể tự hỏi điều gì xảy ra khi một phương thức đồng bộ tĩnh được gọi, vì một phương thức tĩnh được liên kết với một lớp chứ không phải một đối tượng. Trong trường hợp này, luồng thu được khóa nội tại cho đối tượng Class được liên kết với lớp . Do đó, quyền truy cập vào các trường tĩnh của lớp được kiểm soát bởi một khóa khác với khóa đối với bất kỳ trường hợp nào của lớp .
Một phương thức tĩnh cũng có một đối tượng liên quan. Nó thuộc về tệp Class. Class trong bộ công cụ JDK. Khi tệp. Class tải vào ram, Class. Class tạo một thể hiện của nó được gọi là đối tượng mẫu.
Ví dụ: - khi bạn cố gắng tạo đối tượng từ lớp khách hàng hiện tại như
Customer c = new Customer();
Tải khách hàng. Lớp vào RAM. Trong thời điểm đó Class. Class trong bộ công cụ JDK tạo ra một đối tượng được gọi là đối tượng Mẫu và tải Khách hàng đó vào đối tượng khuôn mẫu đó. Các thành viên của Khách hàng đó trở thành các thuộc tính và phương thức trong đối tượng khuôn mẫu đó.
Vì vậy, một phương thức hoặc thuộc tính tĩnh cũng có một đối tượng
Các ví dụ dưới đây cho rõ ràng hơn giữa lớp và khóa đối tượng, hy vọng ví dụ dưới đây cũng sẽ giúp người khác :)
Ví dụ, chúng ta có các phương thức bên dưới một lớp thu nhận và khóa đối tượng thu nhận khác:
public class MultiThread {
public static synchronized void staticLock() throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
public synchronized void objLock() throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
Vì vậy, bây giờ chúng ta có thể có các kịch bản sau đây:
Khi các luồng sử dụng cùng một Đối tượng cố gắng truy cập cùng một phương thức objLock
OR staticLock
(tức là cả hai luồng đang cố truy cập cùng một phương thức)
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Khi các luồng sử dụng cùng một Đối tượng cố gắng truy cập staticLock
và objLock
các phương thức cùng một lúc (cố gắng truy cập các phương thức khác nhau)
Thread-0 0
Thread-1 0
Thread-0 1
Thread-1 1
Thread-0 2
Thread-1 2
Thread-1 3
Thread-0 3
Thread-0 4
Thread-1 4
Khi các luồng sử dụng các đối tượng khác nhau cố gắng truy cập staticLock
phương thức
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Khi các luồng sử dụng các đối tượng khác nhau cố gắng truy cập objLock
phương thức
Thread-0 0
Thread-1 0
Thread-0 1
Thread-1 1
Thread-0 2
Thread-1 2
Thread-1 3
Thread-0 3
Thread-0 4
Thread-1 4
Đối với những người không quen thuộc với phương thức được đồng bộ hóa tĩnh bị khóa trên đối tượng lớp, ví dụ như đối với lớp chuỗi String. Class trong khi phương thức được đồng bộ hóa khóa trên đối tượng hiện tại của đối tượng được biểu thị bởi từ khóa này trong Java. Do cả hai đối tượng này khác nhau nên chúng có khóa khác nhau, vì vậy trong khi một luồng đang thực thi phương thức đồng bộ hóa tĩnh, thì luồng khác trong java không cần đợi luồng đó quay trở lại thay vào đó, nó sẽ thu được khóa riêng được ký hiệu là byte. Class bằng chữ và nhập vào phương pháp đồng bộ tĩnh.