C #: Điều gì sẽ xảy ra nếu một phương thức tĩnh được gọi từ nhiều luồng?


93

Trong Ứng dụng của tôi, tôi có một phương thức tĩnh được gọi từ nhiều luồng cùng một lúc. Có nguy cơ nào về việc dữ liệu của tôi bị trộn lẫn không?

Trong lần thử đầu tiên, phương thức này không phải là static và tôi đang tạo nhiều phiên bản của lớp. Trong trường hợp đó, dữ liệu của tôi bị xáo trộn bằng cách nào đó. Tôi không chắc điều này xảy ra như thế nào vì nó chỉ xảy ra đôi khi. Tôi vẫn đang gỡ lỗi. Nhưng bây giờ phương pháp tĩnh trên tôi không có vấn đề gì cho đến nay. Có lẽ đó chỉ là may mắn. Tôi không biết chắc chắn.


Câu trả lời:


96

Các biến được khai báo bên trong các phương thức (với ngoại lệ có thể là các biến " bị bắt ") được tách biệt, vì vậy bạn sẽ không gặp bất kỳ vấn đề cố hữu nào; tuy nhiên, nếu phương thức tĩnh của bạn truy cập vào bất kỳ trạng thái chia sẻ nào, tất cả các cược sẽ bị tắt.

Ví dụ về trạng thái chia sẻ sẽ là:

  • trường tĩnh
  • các đối tượng được truy cập từ một bộ nhớ cache chung (không được tuần tự hóa)
  • dữ liệu thu được thông qua các tham số đầu vào (và trạng thái trên các đối tượng đó), nếu có thể nhiều luồng đang chạm vào cùng (các) đối tượng

Nếu bạn đã chia sẻ trạng thái, bạn phải:

  • chú ý không thay đổi trạng thái khi nó có thể được chia sẻ (tốt hơn: sử dụng các đối tượng không thay đổi để biểu thị trạng thái và chụp nhanh trạng thái vào một biến cục bộ - nghĩa là thay vì tham chiếu whatever.SomeDatalặp đi lặp lại, bạn đọc whatever.SomeData một lần vào một biến cục bộ và sau đó chỉ cần sử dụng biến - lưu ý rằng điều này chỉ giúp ích cho trạng thái không thay đổi!)
  • đồng bộ hóa quyền truy cập vào dữ liệu (tất cả các chuỗi phải đồng bộ hóa) - trình đọc / ghi loại trừ lẫn nhau hoặc (chi tiết hơn)

1
@Diego - nhận xét đó dành cho tôi hay cho @Holli?
Marc Gravell

Đối với Holli, chỉ để thêm một số thông tin thiết thực vào câu trả lời của bạn.
Diego Pereyra

1
@Marc Tôi không thể hoàn toàn đồng ý với "Các biến được khai báo bên trong các phương thức (với ngoại lệ có thể là các biến" bị bắt ") bị cô lập". Hãy xem xét một xử lý tệp được khai báo trong một phương thức tĩnh. Sau đó, một luồng có thể truy cập vào xử lý khi một số luồng khác sử dụng nó. Nó sẽ dẫn đến hành vi không mong muốn. Hay biến "capture" của bạn cũng có nghĩa là "file handle".
prabhakaran

9
@prabhakaran nếu một xử lý tệp là một biến phương thức, thì nó chỉ được áp dụng cho người gọi đó. Bất kỳ người gọi nào khác sẽ nói chuyện với một biến khác (các biến phương thức là cho mỗi lần gọi). Bây giờ, quyền truy cập vào tệp cơ bản là một vấn đề riêng biệt, nhưng điều đó không liên quan đến c # hoặc .NET. Nếu xử lý không được chia sẻ, người ta sẽ mong đợi một số loại mutex / lock nếu trường hợp này có thể xảy ra.
Marc Gravell

29

Vâng, đó chỉ là may mắn. ;)

Không quan trọng phương thức có tĩnh hay không, điều quan trọng là dữ liệu có tĩnh hay không.

Nếu mỗi luồng có cá thể riêng biệt của lớp với tập dữ liệu riêng của nó, thì không có nguy cơ dữ liệu bị trộn lẫn. Nếu dữ liệu tĩnh, chỉ có một tập dữ liệu và tất cả các luồng đều chia sẻ cùng một dữ liệu, vì vậy không có cách nào để không trộn lẫn nó.

Khi dữ liệu của bạn trong các trường hợp riêng biệt vẫn bị trộn lẫn, rất có thể là do dữ liệu không thực sự riêng biệt.


7
Yêu thích dòng đó - It doesn't matter if the method is static or not, what matters is if the data is static or not. Chỉ cần nói thêm, các biến cục bộ được khai báo trong phạm vi của một phương thức tĩnh không tạo thành một phần dữ liệu mà chúng ta cần phải bận tâm trong tình huống đã cho.
RBT

câu trả lời chính xác. Đã giúp đỡ rất nhiều.
Fractal

15

Phương thức tĩnh sẽ tốt cho nhiều chủ đề.

Mặt khác, dữ liệu tĩnh có thể gây ra sự cố vì các nỗ lực truy cập cùng một dữ liệu từ các luồng khác nhau cần được kiểm soát để đảm bảo rằng chỉ một luồng tại một thời điểm đang đọc hoặc ghi dữ liệu.


2
Từ khóa ở đây là đồng bộ hóa :-)
G. Stoynev 23/12/13

2
đọc là OK để xảy ra đồng thời, nhưng đọc và viết đồng thời sẽ dẫn đến hành vi bất ngờ
Freestyle076

9

MSDN Luôn nói:

Mọi thành viên tĩnh công khai (Được chia sẻ trong Visual Basic) thuộc loại này đều an toàn theo chuỗi. Bất kỳ thành viên cá thể nào đều không được đảm bảo an toàn cho chuỗi.

Chỉnh sửa: Như những người ở đây nói, không phải lúc nào cũng như vậy, và rõ ràng điều này áp dụng cho các lớp được thiết kế theo cách này trong BCL, không áp dụng cho các lớp do người dùng tạo không áp dụng.


3
Phù! Cuối cùng, tôi đã hiểu ý nghĩa của ghi chú này được tìm thấy rất thường xuyên trong tài liệu MSDN. Vì vậy, về cơ bản, khi MS thiết kế một phương thức tĩnh (nơi ghi chú này được xuất bản) trong BCL, họ không truy cập bất kỳ biến / thành viên / trạng thái nào nằm ngoài phạm vi của phương thức đó. Chúng hoàn toàn dựa vào các biến cục bộ trong phạm vi phương thức chỉ để triển khai logic của phương thức đó. Rất vui vì bạn đã chia sẻ.
RBT

@Marcote, điều ngược lại có đúng không? Thành viên phiên bản an toàn vì có một thành viên cho mỗi phiên bản. Tuy nhiên, các thành viên tĩnh không an toàn luồng vì chúng được chia sẻ giữa tất cả các trường hợp của lớp đó? quora.com/…
Fractal

1
nó phụ thuộc. Tôi sẽ không bao giờ coi một thành viên cá thể an toàn theo mặc định. Đó là lý do tại sao một tập hợp toàn bộ thư viện và để tránh hỏng dữ liệu trong số nhiều thứ khác.
Marcote

1
được rồi, cảm ơn @Marcote. Tôi đang dần nhận ra rằng tôi còn rất nhiều điều để học hỏi.
Fractal
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.