2012-05-14 38 views
12

Tôi đã bắt đầu học về tính đồng nhất và chủ đề trong Java. Tôi biết những điều cơ bản của đồng bộ (tức là những gì nó làm). Về mặt khái niệm, tôi hiểu rằng nó cung cấp quyền truy cập độc quyền lẫn nhau của một tài nguyên được chia sẻ với nhiều luồng trong Java. Nhưng khi phải đối mặt với một ví dụ như dưới đây tôi đang bối rối là nó là một ý tưởng tốt để có nó đồng bộ. Tôi biết rằng các phần quan trọng của mã nên được synchorized và từ khóa này không nên bị lạm dụng hoặc nó ảnh hưởng đến hiệu suất.Đồng bộ hóa, Khi nào hoặc không sử dụng?

public static synchronized List<AClass> sortA(AClass[] aArray) 
{ 
    List<AClass> aObj = getList(aArray); 

    Collections.sort(aObj, new AComparator()); 

    return aObj; 
} 

public static synchronized List<AClass> getList(AClass[] anArray) 
{ 
    //It converts an array to a list and returns 
} 
+2

Không đồng bộ cần thiết bởi vì phương pháp của bạn có vẻ không quốc tịch. – Luca

Trả lời

9

Giả sử mỗi luồng vượt qua một mảng khác thì không cần đồng bộ hóa, vì phần còn lại của biến là cục bộ.

Nếu thay vào đó bạn bắn ra một vài đề bài gọi sortA và đi qua một tham chiếu đến cùng một mảng, bạn sẽ gặp rắc rối mà không synchronized, bởi vì họ sẽ can thiệp với eachother.

Hãy coi chừng, có vẻ như từ ví dụ phương pháp getList trả về một List mới từ một mảng, chẳng hạn như khi chuỗi vượt qua cùng một mảng, bạn sẽ nhận được các đối tượng List khác nhau. Điều này là gây hiểu lầm. Ví dụ, sử dụng Arrays.asList tạo ra một List được hỗ trợ bởi các mảng nhất định, nhưng javadoc rõ ràng nói rằng Changes to the returned list "write through" to the array. vì vậy hãy cẩn thận về điều này.

2

Phương pháp tĩnh của bạn không phụ thuộc vào bất kỳ trạng thái được chia sẻ nào, vì vậy không cần đồng bộ hóa.

2

Không có quy tắc nào được xác định như thời điểm sử dụng đồng bộ và khi không, khi bạn chắc chắn rằng mã của bạn sẽ không được truy cập bởi chủ đề đồng thời thì bạn có thể tránh sử dụng đồng bộ hóa.

2

Đồng bộ hóa như bạn đã xác định chính xác có tác động đến thông lượng của ứng dụng của bạn và cũng có thể dẫn đến việc dừng luồng.

Tất cả về cơ bản không nên chặn vì Bộ sưu tập theo gói đồng thời đã được triển khai.

Như trong ví dụ của bạn, tất cả chuỗi cuộc gọi sẽ vượt qua bản sao của mảng, getList không cần phải được đồng bộ hóa như vậy là phương pháp sortA vì tất cả các biến khác đều là cục bộ.

Biến cục bộ trực tiếp trên ngăn xếp và mỗi chuỗi có ngăn xếp riêng để các luồng khác không thể can thiệp vào nó.

Bạn cần đồng bộ hóa khi thay đổi trạng thái của đối tượng mà các chuỗi khác sẽ thấy ở trạng thái nhất quán, nếu cuộc gọi của bạn không thay đổi trạng thái của đối tượng bạn không cần đồng bộ hóa.

3

Đồng bộ hóa thường là cần thiết khi bạn đang chia sẻ dữ liệu giữa nhiều lần gọi và có khả năng dữ liệu sẽ được sửa đổi dẫn đến sự thiếu nhất quán. Nếu dữ liệu là chỉ đọc thì bạn không cần phải đồng bộ hóa.

Trong đoạn mã ở trên, không có dữ liệu nào đang được chia sẻ. Các phương thức hoạt động trên đầu vào được cung cấp và trả về kết quả đầu ra. Nếu nhiều luồng gọi một phương thức của bạn, mỗi lời gọi sẽ có đầu vào và đầu ra của riêng nó. Do đó, không có cơ hội nhất quán ở bất cứ đâu. Vì vậy, các phương pháp của bạn trong đoạn mã trên không cần phải được đồng bộ hóa.

Đồng bộ hóa, nếu sử dụng không cần thiết, chắc chắn sẽ làm giảm hiệu suất do các chi phí liên quan và do đó chỉ nên thận trọng khi được yêu cầu.

+0

Làm cách nào để bạn biết rằng không có dữ liệu nào đang được chia sẻ? Các luồng có thể truyền cùng một mảng tới phương thức 'sortA'. – Tudor

+1

Khá khả năng! Vâng, trong trường hợp đó bạn chắc chắn sẽ cần phải đồng bộ hóa. Vấn đề là người dùng mã phải biết mã của bạn có an toàn hay không. Là nhà phát triển, bạn biết liệu mã của bạn có nên là chuỗi an toàn hay không. Nếu không thì bạn cần phải ghi lại nó cho người dùng để họ có thể đồng bộ hóa rõ ràng trong các tình huống thú vị. Bạn không cần phải đi về việc đồng bộ hóa mọi thứ trong mã của bạn. – Drona

+1

Đồng bộ hóa một phương pháp tĩnh trong đoạn mã ở trên cho chức năng mà nó cung cấp là không chính xác. Người dùng nên bảo vệ chống lại kịch bản mà bạn đã đề cập bên ngoài ở bất cứ đâu. – Drona

2

Tôi sẽ không sử dụng synchronized trên mã đơn luồng. tức là nơi không có cơ hội một đối tượng sẽ được truy cập bởi nhiều luồng.

này có thể xuất hiện rõ ràng nhưng ~ 99% StringBuffer được sử dụng trong JDK chỉ có thể được sử dụng bởi một thread có thể được thay thế bằng một StringBuilder (không đồng bộ)

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