2012-04-17 28 views
20

Tôi có hai đề Thread1Thread2đối tượng đồng bộ thiết lập để null

//Within Thread1  
synchronized(obj1) 
{ 
    obj1 = null; 
} 

//Within Thread2 
synchronized(obj1) 
{ 
    do something 
} 

Nếu JVM đầu tiên thực hiện thread1 và đặt obj1 để null, sau đó sẽ thread2 thấy sự thay đổi ngay lập tức hoặc nó sẽ mất thời gian và JVM vẫn có thể chạy khối đồng bộ thread2 kể từ obj1 chưa được null?

+7

@ KorhanÖztürk Anh ấy không thể thử bản thân mình, bất kỳ loại vấn đề liên quan đến đồng thời nào cũng không xác định. Những loại nhận xét này cực kỳ bực bội khi bối cảnh không được biết đến. –

Trả lời

28

Điều này gần như chắc chắn sẽ phá vỡ trừu tượng đồng bộ hóa - Tôi sẽ không tự tin rằng thread2 sẽ thấy thay đổi ngay lập tức. Bạn không bao giờ nên thay đổi tham chiếu của đối tượng mà bạn đang đồng bộ hóa, ít đặt nó thành null, điều này sẽ gây ra NullPointerException cho bất kỳ nỗ lực nào khác để đồng bộ hóa trên đối tượng đó.

9

Trước tiên hãy để tôi nhấn mạnh rằng việc sửa đổi biến được sử dụng để đồng bộ hóa là điều khủng khiếp xấu ™. obj1 phải là final và không bao giờ được chạm vào nếu nó được sử dụng làm màn hình.

đó đang được nói, trở lại câu hỏi của bạn:

Nếu JVM đầu tiên thực hiện thread1, nó đồng bộ hóa trên obj1, đặt nó vào null và các lối ra chủ đề. Chuỗi thứ hai muốn đồng bộ hóa trên obj1, NullPointerException sẽ bị ném. Bởi vì sửa đổi của obj1 được thực hiện trong khối đồng bộ, nó được đảm bảo rằng Thread2 sẽ thấy giá trị cập nhật (vì vậy: NullPointerException được đảm bảo).

Nếu Thread1 bị gián đoạn sau khi lấy khóa trên obj1 nhưng trước khi xóa tham chiếu, Thread2 sẽ khóa obj1 và đợi cho đến khi Thread1 kết thúc. Sau đó, nó sẽ nhập thành công màn hình vì đối tượng trước đó được tham chiếu bởi obj1 vẫn tồn tại.

+0

vì obj1 đang được sử dụng trong điều kiện được đồng bộ hóa và không nằm trong khối được đồng bộ hóa, có thể cả hai chủ đề cố gắng đồng bộ hóa cùng một lúc và thread1 vào đầu tiên và luồng2 lưu trữ giá trị của obj1.khi thread1 thoát thread2 lấy giá trị của obj1 từ cache và đi vào khối đồng bộ và thấy sự thay đổi trong khối đồng bộ – vjk

+0

@Tomsaz Tôi không nhận được câu lệnh này của bạn _If Thread1 bị gián đoạn sau khi lấy khóa trên obj1 nhưng trước khi xóa tham chiếu, Thread2 sẽ khóa trên obj1 và đợi cho đến khi Thread1 xong_ Bây giờ trước hết chúng ta ngắt thread chỉ khi chúng bị khóa và dù sao chúng không bị chặn thì chúng không có hiệu lực, đúng không? Về cơ bản tôi không bao giờ nhìn thấy một trường hợp mà thread1 sẽ từ bỏ khóa mà không hoàn thành khối đồng bộ hoặc không chờ đợi() nhận được gọi trên khóa đó chính nó. IOW, khi nào và tại sao thread2 sẽ nhận được khóa nhưng vẫn sẽ chờ thread1 để kết thúc. – sactiw

4

synchronized đồng bộ hóa trên đối tượng chứ không phải tham chiếu. Bằng cách đặt obj1 (tham chiếu) thành null, thread2 không thể đồng bộ hóa trên đối tượng trước đây được trỏ đến bởi obj1, thay vào đó, bạn sẽ nhận được NullPointerException.

0

Thay đổi là ngay lập tức. Khi Thread 1 "sở hữu" khóa, nó có thể thay đổi giá trị của obj1 theo ý muốn. Chủ đề 2 phải đợi cho đến khi Thread 1 giải phóng khóa. Nó chắc chắn sẽ thấy obj1 == null

1

Khắc phục nhanh là làm cho đối tượng một mảng đơn giản của 1 phần tử và tham khảo các mảng để đồng bộ hóa, ví dụ,

Object [] obj1 = {rỗng};

Phần tử có thể rỗng mà không ảnh hưởng đến sự tồn tại của mảng. Cấp, điều này vẫn phá vỡ các "quy tắc" của việc không sử dụng các đối tượng chính nó trong đồng bộ hóa, nhưng trừ khi mã của bạn phức tạp vấn đề ở nơi khác, sửa chữa nhanh chóng này sẽ làm việc như mong đợi.

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