2011-10-05 34 views
5

Tôi có lớp sau:sự khác biệt giữa các phương pháp JVM không đồng bộ đồng bộ và

public class SeqGenerator { 

    int last = 0; 
    volatile int lastVolatile = 0; 

    public int getNext() { 
     return last++; 
    } 

    public synchronized int getNextSync() { 
     return last++; 
    } 

    public int getNextVolatile() { 
     return lastVolatile++; 
    } 

    public void caller() { 
     int i1 = getNext(); 
     int i2 = getNextSync(); 
     int i3 = getNextVolatile(); 
    } 

} 

Khi tôi nhìn vào mã tháo rời tôi không thấy sự khác biệt giữa các đại diện của ba phương pháp getNext(), getNextSync()getNextVolatile() .

public int getNext(); 
    Code: 
    0: aload_0 
    1: dup 
    2: getfield #2; //Field last:I 
    5: dup_x1 
    6: iconst_1 
    7: iadd 
    8: putfield #2; //Field last:I 
    11: ireturn 

public synchronized int getNextSync(); 
    Code: 
    0: aload_0 
    1: dup 
    2: getfield #2; //Field last:I 
    5: dup_x1 
    6: iconst_1 
    7: iadd 
    8: putfield #2; //Field last:I 
    11: ireturn 

public int getNextVolatile(); 
    Code: 
    0: aload_0 
    1: dup 
    2: getfield #3; //Field lastVolatile:I 
    5: dup_x1 
    6: iconst_1 
    7: iadd 
    8: putfield #3; //Field lastVolatile:I 
    11: ireturn 

public void caller(); 
    Code: 
    0: aload_0 
    1: invokevirtual #4; //Method getNext:()I 
    4: istore_1 
    5: aload_0 
    6: invokevirtual #5; //Method getNextSync:()I 
    9: istore_2 
    10: aload_0 
    11: invokevirtual #6; //Method getNextVolatile:()I 
    14: istore_3 
    15: return 

Cách JMV có thể phân biệt giữa các phương pháp này?

Mã được tạo giống với các phương pháp này và cả người gọi của họ. Cách JVM thực hiện đồng bộ hóa?

Trả lời

6

Từ khóa synchronized được áp dụng cho phương pháp chỉ đặt cờ ACC_SYNCHRONIZED trên định nghĩa phương thức đó, như được định nghĩa trong the JVM specification § 4.6 Methods. Nó sẽ không được hiển thị trong bytecode thực tế của phương thức.

Các JLS § 8.4.3.6 synchronized Methods thảo luận về sự giống nhau của việc xác định một phương pháp synchronized và tuyên bố một khối synchronized kéo dài cơ thể toàn bộ phương pháp (và sử dụng cùng một đối tượng để đồng bộ hóa trên): các hiệu lực thi hành là giống hệt nhau, nhưng họ được đại diện khác nhau trong tệp .class.

Một hiệu ứng tương tự xảy ra với volatile lĩnh vực: Nó chỉ đơn giản đặt ACC_VOLATILE cờ trên lĩnh vực (JVM § 4.5 Fields). Mã mà truy cập trường sử dụng cùng một mã byte nhưng hoạt động hơi khác.

Cũng xin lưu ý rằng việc sử dụng chỉ một lĩnh vực không ổn định ở đây là không threadsafe, vì x++ trên một lĩnh vực dễ bay hơi xkhông nguyên tử!

4

Sự khác biệt giữa hai người đầu tiên là ngay tại đây:

public int getNext(); 
    bytecodes follow... 

public synchronized int getNextSync(); 
    bytecodes follow... 

Đối với người cuối cùng, volatile là một tài sản của biến, không phải của các phương pháp hay bytecode JVM rằng truy cập rằng biến. Nếu bạn nhìn vào phía trên cùng của javap đầu ra, bạn sẽ thấy như sau:

int last; 

volatile int lastVolatile; 

nếu/khi bytecode được biên dịch thành mã máy bởi trình biên dịch JIT, tôi chắc chắn kết quả mã máy sẽ khác nhau cho phương pháp cuối cùng.

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