2010-09-15 38 views

Trả lời

38

Không, điều đó không có nghĩa là. "Khóa cấp độ lớp" chỉ là một khóa thông thường trên một đối tượng khác, cụ thể là SomeClass.class. Khóa "khóa mức đối tượng" khóa trên this.

Edit: Chỉ cần chắc chắn rằng tôi đang theo sự hiểu biết của bạn về các thuật ngữ, bạn đang tự hỏi nếu m1 và m2 có thể chạy đồng thời khi chúng được định nghĩa dưới đây:

public class SomeClass { 
    public synchronized static void m1() { 
     //do something 
    } 

    public synchronized void m2() { 
     //do something 
    } 
} 

Và câu trả lời là có, m1 và m2 có thể chạy đồng thời. Nó có chức năng tương đương với điều này:

public class SomeClass { 
    public static void m1() { 
     synchronized (SomeClass.class) { 
      //do something 
     } 
    } 
    public void m2() { 
     synchronized (this) { 
      //do something 
     } 
    } 
} 

Vì chúng đang đồng bộ hóa trên các đối tượng hoàn toàn khác nhau, chúng không loại trừ lẫn nhau.

+1

nếu cả hai phương pháp được khai báo là tĩnh thì sao? Tôi tin rằng trong trường hợp đó, cả hai sẽ trở nên loại trừ lẫn nhau, đúng không? – buch11

+2

@ buch11: Đúng vậy, nó sẽ giống như cả hai đang làm 'đồng bộ (SomeClass.class) {...}', và chặn bất kỳ kịch bản tải lớp phức tạp nào, đây sẽ là cùng một đối tượng trong cả hai trường hợp. Về mặt kỹ thuật, việc nạp lớp cho phép bạn có hai "tải trọng" riêng biệt của cùng một lớp và bạn có thể chạy các phương thức đồng bộ tĩnh trong các lớp khác nhau song song. Nhưng ngăn chặn sự vui nhộn đó, nó loại trừ lẫn nhau. –

+0

Bạn có thể tự hỏi điều gì xảy ra khi một phương thức đồng bộ hóa 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, không phải là một đối tượng. Trong trường hợp này, thread thu được khóa nội tại cho đối tượng Class được liên kết với lớp đó. ** Do đó 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. ** [Nguồn] (https://docs.oracle.com/javase/tutorial/essential/concurrency /locksync.html) – Eduardo

6

Trong java có hai loại ổ khóa:

  1. Lớp Cấp
  2. Object Cấp

Trong trường hợp các phương pháp tĩnh khóa luôn kiểm tra trên lớp nhưng trong trường hợp sơ thẩm phương pháp khóa luôn được kiểm tra trên đối tượng.

Ví dụ:

show1()phi tĩnhshow()tĩnh. Bây giờ, show() được gọi bằng tên lớp (hoặc theo đối tượng) và show1() được gọi theo đối tượng, sau đó cả hai phương pháp có thể truy cập đồng thời bởi hai luồng.

class Shared{ 
    static int x; 
    static synchronized void show(String s,int a){ 
     x=a; 
     System.out.println("Starting in method "+s+" "+x); 
     try{ 
      Thread.sleep(2000); 
     } 
     catch(Exception e){ } 
     System.out.println("Ending from method "+s+" "+x); 
    } 
    synchronized void show1(String s,int a){ 
     x=a; 
     System.out.println("Starting show1 "+s); 
     try{ 
      Thread.sleep(2000); 
     } 
     catch(Exception e){ } 
     System.out.println("Ending from show1 "+s); 
    } 
} 
class CustomThread extends Thread{ 
    Shared s; 
    public CustomThread(Shared s,String str){ 
     super(str); 
     this.s=s; 
     start(); 
    } 
    public void run(){ 
     Shared.show(Thread.currentThread().getName(),10); 
    } 
} 
class CustomThread1 extends Thread{ 
    Shared s; 
    public CustomThread1(Shared s,String str){ 
     super(str); 
     this.s=s; 
     start(); 
    } 
    public void run(){ 
     s.show1(Thread.currentThread().getName(),20); 
    } 
} 
public class RunSync { 
    public static void main(String[] args) { 
     Shared sh=new Shared(); 
     CustomThread t1=new CustomThread(sh,"one"); 
     CustomThread1 t2=new CustomThread1(sh,"two"); 
    } 
} 

Output:

Starting in method one 10 
Starting show1 two 
Ending from method one 20 
Ending from show1 two   
12

mức Object khóa:

Object cấp khóa là cơ chế khi bạn muốn đồng bộ hóa một khối mã phương pháp không tĩnh hay không tĩnh như vậy mà chỉ một thread sẽ có thể thực thi khối mã trên cá thể đã cho của lớp. Điều này nên luôn luôn được thực hiện để làm cho thread dữ liệu cấp độ thể hiện an toàn. Điều này có thể được thực hiện như sau:

public class DemoClass 
{ 
    public synchronized void demoMethod(){} 
} 

or 

public class DemoClass 
{ 
    public void demoMethod(){ 
    synchronized (this) 
    { 
    //other thread safe code 
    } 
} 
} 

or 

public class DemoClass 
{ 
    private final Object lock = new Object(); 
    public void demoMethod(){ 
    synchronized (lock) 
{ 
    //other thread safe code 
} 
} 

Lớp cấp khóa:

Lớp cấp khóa ngăn ngừa nhiều chủ đề để vào trong khối đồng bộ trong bất kỳ tất cả các trường có sẵn trên runtime. Điều này có nghĩa là nếu trong thời gian chạy có 100 phiên bản của DemoClass, thì chỉ có một luồng sẽ có thể thực thi demoMethod() trong bất kỳ trường hợp nào tại một thời điểm và tất cả các phiên bản khác sẽ bị khóa cho các luồng khác. Điều này nên luôn luôn được thực hiện để làm cho luồng dữ liệu tĩnh an toàn.

public class DemoClass 
{ 
    public synchronized static void demoMethod(){} 
} 

or 

public class DemoClass 
{ 
    public void demoMethod(){ 
    synchronized (DemoClass.class) 
    { 
    //other thread safe code 
    } 
} 
} 

or 

public class DemoClass 
{ 
private final static Object lock = new Object(); 
public void demoMethod(){ 
synchronized (lock) 
    { 
    //other thread safe code 
    } 
} 
} 
2

Ví dụ để hiểu đối tượng và trình độ lớp khóa trong Java

1) Object Cấp dụ khóa

package com.test; 

public class Foo implements Runnable { 

    @Override 
    public void run() { 
     Lock(); 
    } 
    public void Lock() { 
     System.out.println(Thread.currentThread().getName()); 
     synchronized(this) { 
      System.out.println("in block " + Thread.currentThread().getName()); 
      System.out.println("in block " + Thread.currentThread().getName() + " end"); 
     } 
    } 

    public static void main(String[] args) { 
     Foo b1 = new Foo(); 
     Thread t1 = new Thread(b1); 
     Thread t2 = new Thread(b1);    
     Foo b2 = new Foo(); 
     Thread t3 = new Thread(b2);    
     t1.setName("t1"); 
     t2.setName("t2"); 
     t3.setName("t3");    
     t1.start(); 
     t2.start(); 
     t3.start(); 
    } 
} 

đầu ra:

t1 
    t3 
    t2 
    in block t3 
    in block t1 
    in block t3 end 
    in block t1 end 
    in block t2 

Lưu ý rằng t3 sẽ không chặn khi chuỗi t1 và t2 bị chặn. Bởi vì khóa được đặt trên đối tượng này và đề t3 có khác nhau đối tượng này hơn chủ đề t1, t2

2) Lớp Cấp khóa dụ

Các mã trong khóa cấp độ đối tượng, chỉ Foo.class là được thêm vào trong khối được đồng bộ hóa. Tất cả các chủ đề đang được tạo ra bằng cách sử dụng đối tượng của lớp Foo sẽ bị chặn.

package com.test;  
public class Foo implements Runnable {   
    @Override 
    public void run() { 
     Lock(); 
    } 

    public void Lock() { 
     System.out.println(Thread.currentThread().getName()); 
     synchronized(Foo.class) { 
      System.out.println("in block " + Thread.currentThread().getName()); 
      System.out.println("in block " + Thread.currentThread().getName() + " end"); 
     } 
    } 

    public static void main(String[] args) { 
     Foo b1 = new Foo(); 
     Thread t1 = new Thread(b1); 
     Thread t2 = new Thread(b1);    
     Foo b2 = new Foo(); 
     Thread t3 = new Thread(b2);    
     t1.setName("t1"); 
     t2.setName("t2"); 
     t3.setName("t3");    
     t1.start(); 
     t2.start(); 
     t3.start(); 
    } 
} 

đầu ra:

t1 
t3 
in block t1 
in block t1 end 
t2 
in block t3 
in block t3 end 
in block t2 
in block t2 end 

khối đồng bộ sẽ được thực hiện đối với các chủ đề tương tự.

0

Có thể cả phương pháp đồng bộ hóa tĩnh và không đồng bộ tĩnh đều có thể chạy đồng thời hoặc đồng thời vì chúng khóa trên đối tượng khác.

Courtesy

1

khóa mức Class được thực hiện bằng từ khóa "tĩnh đồng bộ, trong khi đó mức đối tượng được thực hiện chỉ bằng từ khóa synchronized. Object khóa cấp độ được thực hiện để hạn chế tương tự đối tượng để vận hành thông qua chủ đề khác nhau, trong đó khi khóa cấp độ được thực hiện để hạn chế bất kỳ đối tượng nào hoạt động.

0

Những cách khác nhau có trình độ lớp khóa: 1) public class DemoClass {

public static synchronized void demoMethod(){ 
    //dosomething 
} 

}

2)

public class DemoClass {

public void demoMethod(){ 

    synchronized(DemoClass.class){ 
     //dosomething 
    } 
} 

}

3)

public class DemoClass {

private final static Object lock = new Object(); 
public void demoMethod(){ 

    synchronized(lock){ 
     //dosomething 
    } 
} 

}

+0

Cách này trả lời câu hỏi? – shmosel

0

khóa mức Class và dụ mức khóa cả hai đều khác nhau. Cả hai đều không ảnh hưởng đến trạng thái khóa khác. Nếu một phiên bản của một lớp đã bị khóa bởi một luồng thì một luồng khác sẽ không thể khóa cho cá thể đó cho đến khi trừ khi khóa được giải phóng bởi chuỗi đầu tiên. Hành vi tương tự có ở đó để khóa cấp độ lớp.

Nhưng nếu một chủ đề mua khóa cấp Lớp thì một luồng khác có thể lấy khóa trên một trong các thể hiện của nó. Cả hai có thể làm việc parallel.`

package lock; 

class LockA implements Runnable { 
    @Override 
    public void run() { 
     synchronized (LockA.class) { 
      System.out.println("Class"); 
      try { 
       Thread.sleep(60 * 1000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 
public class TestClassVsInstanceLock { 
    public static void main(String[] args) { 
     final LockA a = new LockA(); 
     final LockA b = new LockA(); 
     try { 
      Thread t = new Thread(a); 
      Thread t1 = new Thread() { 
       @Override 
       public void run() { 
        synchronized (b) { 
         System.out.println("Instance 1"+ currentThread().currentThread().holdsLock(b)); 
         try { 
          Thread.sleep(10 * 1000); 
         } catch (InterruptedException e) { 
          e.printStackTrace(); 
         } 
        } 
       } 
      }; 
      t.start(); 
      t1.start(); 
      synchronized (a) { 
       System.out.println("Instance2"); 
       Thread.sleep(10 * 1000); 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

'

này sẽ in: - Instance2 Lớp Instance 1true

Tất cả sẽ được in ngay lập tức mà không cần bất kỳ tạm dừng.

2

Nếu thread T1 nhập phương thức m1 bằng cách lấy khóa cấp lớp, điều này có nghĩa là một luồng T2 khác không thể chạy phương thức khác m2 bằng cách lấy khóa mức đối tượng không?

Khóa cấp đối tượng và Khóa cấp lớp khác nhau. Trong trường hợp trên, T2 có thể chạy phương thức m2 bằng cách lấy khóa mức đối tượng. Nhưng nếu m2 là static synchronized, T2 không thể gọi phương thức m2 trừ khi khóa cấp phát hành lớp T1 trên phương thức m1.

Object level lock:

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 phương thức synchronized cho một đối tượng, tất cả các luồng khác gọi phương thức synchronized cho cùng một khối đối tượng (tạm dừng thực hiện) cho đến khi chuỗi đầu tiên được thực hiện với đối tượng.

Giả sử rằng bạn có hai phương thức synchronized m1 và m2 trên đối tượng O. Nếu luồng T1 đang ở giữa thực hiện phương pháp m1, thì T2 phải đợi để gọi phương thức m2 trên cùng đối tượng O trừ khi khóa bản phát hành luồng T1 trên phương pháp m1.

Class level lock:

Chủ đề mua lại các khóa nội tại cho đối tượng Class gắn liền với lớp. Do đó quyền truy cập vào các trường static 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ỳ trường hợp nào của lớp.

Giả sử phương thức m1 là static synchrnozed và phương pháp m2 cũng là static synchronized và bạn có hai đối tượng khác nhau o1 và o2.

Nếu chủ đề T1 đang ở giữa thực hiện phương pháp m1 trên đối tượng o1, thì T2 phải chờ để gọi phương thức m2 trên đối tượng o2 trừ khi bản phát hành Thread T1 khóa trên phương thức m1.

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