Khi chúng ta nói về khóa nội tại, chúng ta đề cập đến đối tượng mà chúng ta yêu cầu khóa hoặc cho phương pháp đồng bộ?thread nội tại khóa
Khóa ở trên đối tượng hoặc trên phương pháp đồng bộ hóa của nó?
Tôi đang bối rối!
Khi chúng ta nói về khóa nội tại, chúng ta đề cập đến đối tượng mà chúng ta yêu cầu khóa hoặc cho phương pháp đồng bộ?thread nội tại khóa
Khóa ở trên đối tượng hoặc trên phương pháp đồng bộ hóa của nó?
Tôi đang bối rối!
phương pháp đồng bộ khóa phương pháp trên đối tượng
synchronized void methodA() {
....
}
là bằng cách nào đó tương đương với
void methodA() {
synchronized (this) {
....
}
}
khóa Intrinsic đang trên đối tượng:
class A
{
public synchronized void method1(){...}
public synchronized void method2(){...}
}
Nếu thread A là trong method1 sau đó threadB không thể nhập method2.
Tôi muốn, Stackoverflow cho phép tôi +10 cho dòng cuối cùng của bạn. :) – UnKnown
Khóa là một phần của đối tượng. Mỗi đối tượng có một và nó có thể bị khoá theo hai cách:
synchronized
sửa đổi trên một phương pháp thể hiện của các lớp để khóa các đối tượng liên quan đếnsynchronized(object) {}
Tương tự như vậy, bạn có thể khóa Lớp đối tượng thay vì chính Đối tượng (đề cập riêng biệt để hiểu công cụ sửa đổi synchronized
với phương pháp static
):
synchronized
sửa đổi trên một phương pháp tĩnh của lớp để khóa Lớpsynchronized(clazz) {}
nơi clazz
là Lớp ObjectLock đang bật đối tượng. Trong Java mỗi đối tượng là một monitor
Trong Java, một khóa bên trong được ngụ ý bởi mỗi lần sử dụng từ khóa synchronized
Mỗi sử dụng từ khóa synchronized được kết hợp với một trong hai loại khóa nội tại:
một "khóa dụ", gắn liền với một đối tượng duy nhất
một "tĩnh khóa", gắn liền với một lớp
Nếu một phương pháp được khai báo là đồng bộ, sau đó nó sẽ có được một trong hai khóa dụ hoặc khóa tĩnh khi nó được gọi, theo cho dù đó là một phương thức thể hiện hay một phương thức tĩnh.
Hai loại khóa có hành vi tương tự nhau, nhưng hoàn toàn độc lập với nhau.
Lấy khóa thể hiện chỉ chặn các chủ đề khác yêu cầu phương thức thể hiện được đồng bộ hóa; nó không chặn các luồng khác yêu cầu một phương thức không đồng bộ hóa, cũng không chặn chúng khỏi việc gọi một phương thức đồng bộ hóa tĩnh.
Tương tự, việc mua khóa tĩnh chỉ chặn các luồng khác yêu cầu phương thức đồng bộ hóa tĩnh; nó không chặn các luồng khác khỏi việc gọi ra một phương thức không đồng bộ, cũng không chặn chúng khỏi việc gọi một phương thức thể hiện được đồng bộ hóa.
Bên ngoài tiêu đề phương pháp, đồng bộ hóa (điều này) có được khóa thể hiện.
Các khóa tĩnh có thể được mua bên ngoài của một tiêu đề phương pháp trong hai cách:
đồng bộ (Blah.class), sử dụng các lớp đen
đồng bộ (this.getClass()), nếu một đối tượng có sẵn
private int count = 0;
public synchronized void countFunc(){
count++;
}
Thread t1 = new Thread(new Runnable(){
public void run(){
for(int i=0;i<1000;i++){
countFunc();
}}});
Thread t2 = new Thread(new Runnable(){
public void run(){
for(int i=0;i<1000;i++){
countFunc();
}}});
Trong ví dụ trên, tôi có 2 chủ đề cố gắng tăng giá trị đếm. Và để ngăn chặn luồng xen kẽ, tôi đang cố gắng lấy một khóa nội tại bằng cách sử dụng đồng bộ hóa từ khóa.
cách thuyết phục, Trong ví dụ này, khóalà phương pháp khối countFunc với đồng bộ từ khóa và khóalàtrên các đếm biến. Hy vọng điều này sẽ giúp
Khóa trên Object.
Có một cái nhìn tại trang hướng dẫn java trên intrinsic locks
Mỗi đối tượng có một khóa bên trong liên kết với nó. Theo quy ước, một luồng cần truy cập độc quyền và nhất quán vào các trường của đối tượng phải lấy khóa nội tại của đối tượng trước khi truy cập chúng, và sau đó giải phóng khóa nội tại khi nó được thực hiện với chúng. Một sợi dây được cho là sở hữu khóa bên trong giữa thời gian nó có khóa và mở khóa.
Miễn là một chủ sở hữu có khóa nội tại, không có chuỗi nào khác có thể có cùng khóa. Các chủ đề khác sẽ chặn khi nó cố gắng để có được khóa.
Hai cách sử dụng ổ khóa bên trong:
phương pháp đồng bộ:
Khi một thread gọi một phương pháp synchronized
, nó tự động mua lại các nội khóa cho đối tượng của phương pháp đó và giải phóng nó khi phương thức trả về.
ví dụ:
public synchronized void incrementCounter(){
++counter;
}
báo cáo đồng bộ
Không giống như các phương pháp synchronized
, synchronized
báo cáo phải ghi rõ đối tượng cung cấp các khóa nội
public int getCounter(){
synchronized(this){
return counter;
}
}
Complete dụ:
public class SynchronizedDemo{
private int counter = 0;
public SynchronizedDemo(){
}
public synchronized void incrementCounter(){
++counter;
}
public int getCounter(){
synchronized(this){
return counter;
}
}
public static void main(String[] args){
SynchronizedDemo object = new SynchronizedDemo();
for (int i=0; i < 5; i++){
Thread t = new Thread(new SimpleRunnable(object));
t.start();
}
}
}
class SimpleRunnable implements Runnable{
private SynchronizedDemo object;
public SimpleRunnable(SynchronizedDemo obj){
this.object = obj;
}
public void run(){
object.incrementCounter();
System.out.println("Counter:"+object.getCounter());
}
}
Lưu ý: Ví dụ này chỉ được viết để giới thiệu các cách sử dụng khóa nội tại khác nhau. Sử dụng AtomicInteger cho biến số lượt truy cập là cách tiếp cận đúng cho loại trường hợp sử dụng này.
Mọi đối tượng đều có khóa nội tại. Hai câu lệnh này là tương đương vì cả hai đều đồng bộ hóa trên khóa nội tại của đối tượng chứa phương thứcA(). – Brandon
Giải thích các câu lệnh Đồng bộ hóa cho một người không hiểu các Phương thức đồng bộ hóa không phải là một ý tưởng hay. Điều này chỉ làm tôi bối rối hơn nữa. –