2009-08-08 24 views
18

Vì vậy, tất cả chúng ta đã thấy thông báo Luồng trên MSDN cho nhiều đối tượng chung sẵn có:Điều gì khiến cho các thành viên trong ví dụ không an toàn và công khai tĩnh?

"Thành viên công cộng (Được chia sẻ trong Visual Basic) là loại an toàn. . "

Câu hỏi của tôi là, nó là gì về việc biến thể hiện so với tĩnh công cộng làm cho nó không an toàn?

+3

Phần trong dấu ngoặc là nguyên nhân gây nhầm lẫn khi đọc - thay vì đọc nó là: * Thành viên * tĩnh công cộng * thuộc loại này là an toàn chỉ. Điều này có nghĩa rằng các thành viên tĩnh của đối tượng này Type là threadsafe, nó không đề cập đến một "public static Type;" ví dụ được khai báo trong mã của bạn. –

Trả lời

13

Điều này chỉ đúng nói chung.

Trong phương pháp tĩnh chung là tĩnh vì chúng không phụ thuộc vào cũng như không truy cập bất kỳ dữ liệu được xác định thể hiện nào mà một chuỗi khác cũng có thể truy cập. Nói chung, các biến duy nhất chúng (một phương thức tĩnh) sử dụng là các biến được khai báo và gắn với bộ nhớ tĩnh của lớp mà phương thức được thực hiện, không phải bộ nhớ được cấp cho đối tượng - (thể hiện của lớp) được tạo cho đối tượng đó . Một phương thức tĩnh không và không thể tham chiếu hoặc sử dụng bất kỳ biến nào như vậy. Nếu một phương thức sử dụng kiểu biến dữ liệu cá thể này, gắn với một cá thể cụ thể, thì nó không thể là tĩnh. Ngược lại, một phương thức Instance không truy cập một số phần tử dữ liệu (thuộc tính hoặc trường) của cá thể.

Nếu, otoh, một phương pháp tĩnh truy cập thuộc tính tĩnh hoặc trường của lớp, nó cũng không an toàn bằng luồng.

Có bốn điều kiện cần thiết để cuộc đua có thể thực hiện được.

  1. Điều kiện đầu tiên là có các vị trí bộ nhớ có thể truy cập từ nhiều hơn một chuỗi. Thông thường, các vị trí này là các biến toàn cục/tĩnh hoặc là bộ nhớ heap có thể truy cập từ các biến toàn cầu/tĩnh. Điều kiện thứ hai là có một thuộc tính (thường được gọi là bất biến), được liên kết với các vị trí bộ nhớ chia sẻ này phải đúng, hoặc hợp lệ để chương trình hoạt động chính xác. Thông thường, thuộc tính cần giữ đúng trước khi cập nhật xảy ra để cập nhật chính xác.
  2. Điều kiện thứ ba là thuộc tính bất biến không giữ trong một số phần của bản cập nhật thực tế. (Nó là vô hạn hoặc sai trong một số phần của quá trình xử lý).
  3. Điều kiện thứ tư và cuối cùng phải xảy ra cho một cuộc đua xảy ra là một luồng khác truy cập bộ nhớ trong khi bất biến bị hỏng, do đó gây ra hành vi không phù hợp hoặc không chính xác.
8

Đó là vấn đề của tiểu bang. Những gì chung làm cho phương pháp không an toàn cho nhiều chủ đề là họ không truy cập trạng thái chia sẻ trong một thread an toàn. Các phương thức tĩnh nói chung không truy cập trạng thái chia sẻ và do đó ít có khả năng chạy vào vấn đề này. Nó vẫn có thể có điều kiện chủng tộc trong phương pháp tĩnh/chia sẻ nếu họ chạm vào dữ liệu tĩnh nhưng nói chung là phương pháp tĩnh.

+0

Có lẽ bạn nên nhấn mạnh thực tế rằng nó chỉ là 'nói chung' hơn. – Dykam

+0

@Dykam, vâng tôi đã tô đậm phần đó để nhấn mạnh – JaredPar

12

Không có gì inbuilt làm cho tĩnh nữa hoặc ít hơn khác nhau (tái thread-an toàn) hơn Ví dụ, ngoại trừ:

  • phương pháp tĩnh thường không quốc tịch "thuần túy chức năng" phương pháp, làm cho chúng tự động thread-safe
  • có một kỳ vọng rõ ràng đối với các thành viên tĩnh là an toàn chủ đề (vì bạn không thể thực sự kiểm soát những gì mỗi luồng đang thực hiện cùng một lúc) - do đó, được mong đợi nguy cơ thread-an toàn có thể được thực hiện thread-safe

Điều này không đúng cho các phương pháp dụ:

  • phương pháp dụ thường được truy cập nhà nước về mà dụ
  • không có kỳ vọng của chủ đề an toàn trừ khi được nêu rõ trong tài liệu

Vì vậy, nói chung, người gọi quản lý an toàn luồng trên các phiên bản.

Có trường hợp ngoại lệ trong đó các trường hợp an toàn theo luồng (thường là đối với những thứ liên quan chặt chẽ đến luồng, chẳng hạn như hàng đợi của người sản xuất) - nhưng IMO bất kỳ thành viên tĩnh nào không an toàn luồng đều là lỗi.

+1

@marc, tôi khiêm nhường không đồng ý ... không nói rằng điều đó không tồn tại, nhưng tôi chưa bao giờ có kỳ vọng rằng các phương pháp tĩnh là an toàn chỉ, cũng như tôi chưa từng nghe một kỳ vọng như vậy. Các phương thức tĩnh vẫn có thể truy cập các biến tĩnh, (từ bất kỳ lớp nào), cũng như các biến mẫu trong các đối tượng được truyền vào như các tham số phương thức. –

+0

(cont) Cách duy nhất mà bạn mong đợi có thể dựa vào là nếu tất cả các phương pháp tĩnh đều bị cấm sử dụng bất kỳ biến nào được tham chiếu trong biến hoặc tham chiếu các loại tham chiếu và truy cập bất kỳ biến tĩnh nào trong đó hoặc bất kỳ lớp nào khác. Điều này có vẻ là một hạn chế cực kỳ nghiêm trọng, chỉ để cho phép "kỳ vọng" của bạn đáng tin cậy. –

+0

Bạn lý luận không tuân theo. Tôi đang nói về trạng thái tĩnh của chính nó (chẳng hạn như một từ điển tĩnh/danh sách trên một trường tĩnh, được sử dụng bởi phương thức tĩnh), vì điều đó không thể được kiểm soát bởi người gọi. Các phương thức tĩnh thường là thread-safe bởi thủ thuật đơn giản không sử dụng bất kỳ trạng thái riêng nào ;-p Trạng thái của những thứ như 'ref' hoặc ref-type args * được * điều khiển bởi người gọi, và nên được quản lý như vậy. Nó tương tự như vậy không ảnh hưởng đến các cuộc gọi bên ngoài. Kỳ vọng ** là ** ở đó, nếu không bạn sẽ có ** nhiều ** khóa trong hầu hết mọi dòng mã C# của bạn. –

0

Sự cố với phương pháp không an toàn luồng là truy cập đồng thời vào các tài nguyên được chia sẻ chẳng hạn như biến mẫu. Nếu một phương thức tĩnh chỉ hoạt động trên dữ liệu riêng tư/cục bộ, nó vốn đã là chủ đề an toàn. Tuy nhiên, không có gì đảm bảo rằng các phương thức tĩnh làm điều đó - điều này phải được thực hiện một cách rõ ràng. Vì vậy, đối với một phương pháp tĩnh để được an toàn thread nó không thể truy cập các thành viên tĩnh mà không sử dụng đồng bộ hóa và nó nên sao chép bất cứ dữ liệu nào nó nhận được như là đầu vào trước khi sửa đổi nó.

+0

Tại sao dữ liệu riêng tư tĩnh cho các phương thức tĩnh an toàn? – Dykam

+0

Tôi không nói về tư nhân như trong các thành viên tư nhân của loại, nhưng riêng tư như trong địa phương. Bởi vì mỗi thread có ngăn xếp riêng của nó, nơi các miền địa phương được lưu trữ này không được chia sẻ giữa các chủ đề khác nhau và do đó vốn đã an toàn. –

0

TLDR; Các lớp có ghi chú trên sẽ có các phương thức tĩnh an toàn bởi vì các kỹ sư của Microsoft đã viết mã theo một cách an toàn, có lẽ bằng cách sử dụng các khóa hoặc các cơ chế đồng bộ hóa luồng khác " (trích dẫn lấy từ http://odetocode.com/Articles/314.aspx)

Xem chi tiết

nó là gì? Không có gì, ngoại trừ mã được viết cho lớp đó.

Tuyên bố là tuyên bố cho bạn biết rằng các lập trình viên đã viết lớp đã đảm bảo rằng tất cả các thành viên tĩnh (phương pháp và thuộc tính) là an toàn chủ đề (nhưng chưa làm như vậy cho các thành viên).

Đã đảm bảo an toàn là chủ đề an toàn vì tĩnh, rất có khả năng chúng sẽ được gọi bởi nhiều luồng, do đó, chúng đặt thêm công việc cần thiết để đảm bảo điều này sẽ ổn. Thường thì các phương thức tĩnh cũng là các hàm không trạng thái, nghĩa là chúng đã được an toàn chủ đề chung (không cần thêm công việc).

Ngược lại, ví dụ các thành viên, tuyên bố đơn giản là họ nói với bạn rằng họ không cẩn thận với họ.

Trường hợp thường sẽ được tạo bởi một chuỗi duy nhất và chỉ truy cập theo chuỗi đó; nếu cá thể không bao giờ được truy cập bởi nhiều luồng, thì sự an toàn của luồng không phải là vấn đề, do đó các lập trình viên không bận tâm thêm nó.

Tuyên bố không phải là xác nhận quyền sở hữu về bất kỳ thuộc tính cố hữu nào của tĩnh so với phiên bản; cả hai có thể không an toàn trừ khi bạn đặt mã cụ thể vào để đảm bảo nhiều chuỗi có thể truy cập chúng mà không gặp sự cố (hoặc nếu tự nhiên chúng đã là luồng an toàn, ví dụ: chức năng không quốc tịch).

Nó chỉ đơn giản là một tuyên bố rằng các lập trình viên đã viết những lớp học đã đảm bảo rằng các thành viên tĩnh được an toàn, nhưng đã không làm như vậy cho các thành viên ví dụ.

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