2013-08-03 24 views
5

đoạn Mã - 1Đồng bộ hóa quyền truy cập vào đối tượng Immutable Integer

class RequestObject implements Runnable 
{ 
    private static Integer nRequests = 0; 

    @Override 
    public void run() 
    {  
     synchronized (nRequests) 
     { 
      nRequests++; 
     } 
    } 
} 

đoạn Code - 2

class RequestObject implements Runnable 
{ 
    private static Integer nRequests = 0; 
    private static Object lock = new Object(); 

    @Override 
    public void run() 
    {  
     synchronized (lock) 
     { 
      nRequests++; 
     } 
    } 
} 

Trong khi đoạn mã thứ hai đang làm việc tốt mà không gây ra bất kỳ điều kiện chủng tộc, các đầu tiên không thành công trong việc đồng bộ hóa quyền truy cập vào thành viên dữ liệu tĩnh giữa các phiên bản khác nhau của cùng một lớp (RequestObject). Ai đó có thể ném thêm ánh sáng vào điều này. Tôi muốn hiểu tại sao phương pháp đầu tiên không hiệu quả.

Triển khai ban đầu của tôi là triển khai đầu tiên. Sau đó tôi nhìn thấy trong https://stackoverflow.com/a/2120409/134387.

+3

Vì 'Integer' là không thể thay đổi. Tăng nó không làm những gì bạn nghĩ rằng –

+1

cũng không sử dụng Integer, sử dụng 'int' –

+0

Đây là một câu hỏi khác. Hãy làm cho nó một câu hỏi mới. –

Trả lời

6

Bạn liên tục tạo các đối tượng Số nguyên mới, sau đó bạn đồng bộ hóa, ít nhất khiến bạn vô cùng khó hiểu khi nghĩ về nó. Vì vậy, bạn có thể nhận được các tình huống sau:

Chủ đề A được giữ giá trị hiện tại của nRequests (cho phép nói 0)

hàng đợi Thread B cho cùng giá trị (0)

Chủ đề Một tăng nRequests (với giá trị 1)

Chủ đề C giữ giá trị mới và đồng bộ hóa trên giá trị đó, tăng giá trị và cho phép giá trị.

Chủ đề Một buông màn hình trên 0

Thread B đồng bộ hóa trên 0 và tăng nó đến 1, ghi đè lên những thay đổi của C

Với cách tiếp cận thứ hai bạn có một đối tượng duy nhất mà tất cả mọi người phải đồng bộ hóa trên. Đó là chính xác những gì bạn muốn.

4

Trường hợp Integer là không thay đổi, nRequests++ do đó tạo đối tượng Integer mới để giữ kết quả và lưu trữ trong nRequests. Câu lệnh synchronized đồng bộ hóa trên một đối tượng. Do đó, các chủ đề sẽ đồng bộ hóa trên các đối tượng khác nhau. Có, chỉ có thể có một luồng trong một khối đồng bộ trên cùng một đối tượng cùng một lúc, nhưng các luồng khác nhau có thể nằm trong các khối đồng bộ của các đối tượng khác nhau cùng lúc ...

Cách dễ nhất để đồng bộ hóa quyền truy cập vào trạng thái tĩnh được đặt nó trong một phương pháp đồng bộ tĩnh:

static synchronized void increment() { 
    nRequests++; 
} 

này tương đương với khối đồng bộ sau:

synchronized (RequestObject.class) { 
    nRequests++; 
} 

nơi RequestObject là lớp chứa các lĩnh vực tĩnh.

2

Vấn đề là lớp Integer là bất biến trong java. Vì vậy, mỗi thread đồng bộ hóa trên một đối tượng khác nhau bởi vì nRequests++ tạo ra một đối tượng mới trên mỗi lời gọi.

Trong trường hợp thứ hai, đối tượng lock giống nhau đối với mỗi trường hợp và nối tiếp thành công chuỗi các chủ đề với biến số nRequests.

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