Kiểm tra điều kiện cuộc đua đa luồng


54

Đọc các bình luận cho câu trả lời này , cụ thể:

Chỉ vì bạn không thể viết một bài kiểm tra không có nghĩa là nó không bị hỏng. Hành vi không xác định thường xảy ra để hoạt động như mong đợi (C và C ++ có đầy đủ điều đó), điều kiện chủng tộc, sắp xếp lại tiềm năng do mô hình bộ nhớ yếu ... - CodeInChaos 7 giờ trước

@CodesInChaos nếu không thể sao chép thì mã được viết là 'fix' cũng không thể được kiểm tra. Và đưa mã chưa được kiểm tra vào cuộc sống là một tội ác tồi tệ hơn theo quan điểm của tôi - RhysW 5 giờ trước

... Tôi tự hỏi liệu có bất kỳ cách tổng quát tốt nào để liên tục kích hoạt rất thường xuyên xảy ra trong các vấn đề sản xuất gây ra bởi các điều kiện chủng tộc trong trường hợp thử nghiệm.


1
hướng dẫn từng bước (lắp ráp) theo hướng dẫn ở cả hai đầu
ratchet freak

1
Phân tích tĩnh thường có thể hiển thị UB tiềm năng, không rõ liệu điều này có được tính là thử nghiệm hay không
jk.

Xin lỗi, nhưng 'UB' nghĩa là gì?
Doug

2
Câu hỏi hay, tôi sẽ rất thú vị khi thấy các giải pháp tiềm năng cho vấn đề này.
RhysW

1
@Doug Hành vi không xác định, có thể bao gồm, nhưng không giới hạn ở các điều kiện chủng tộc
jk.

Câu trả lời:


85

Sau khi tham gia vào công việc điên rồ này từ khoảng năm 1978, đã dành gần như toàn bộ thời gian đó cho máy tính nhúng thời gian thực, làm việc đa nhiệm, đa luồng, đa hệ thống, đôi khi với nhiều bộ xử lý vật lý, đã theo đuổi nhiều hơn so với cuộc đua công bằng của tôi điều kiện, ý kiến ​​của tôi là câu trả lời cho câu hỏi của bạn khá đơn giản.

Không.

Không có cách chung nào tốt để kích hoạt điều kiện cuộc đua trong thử nghiệm.

Hy vọng duy nhất của bạn là thiết kế chúng hoàn toàn ra khỏi hệ thống của bạn.

Khi và nếu bạn thấy rằng ai đó đã nhét một cái vào, bạn nên đặt anh ta ra một ổ kiến, sau đó thiết kế lại để loại bỏ nó. Sau khi bạn đã thiết kế pas giả của anh ấy (phát âm là f *** up) ra khỏi hệ thống của bạn, bạn có thể giải phóng anh ta khỏi lũ kiến. (Nếu những con kiến ​​đã ăn thịt anh ta, chỉ để lại xương, hãy đặt một dấu hiệu cho biết "Đây là điều xảy ra với những người đưa điều kiện chủng tộc vào dự án XYZ!"


22
Tôi hoàn toàn đồng ý. Nói cách khác, đây giống như trò đùa - Bệnh nhân: "Bác sĩ, thật đau khi tôi làm điều này ..." Bác sĩ: "Vậy thì đừng làm nữa!"
Mark Rushakoff

Câu trả lời tốt đẹp. Nếu một cái gì đó gây ra một vấn đề không thể kiểm tra, hãy cố gắng làm việc xung quanh nó để bắt đầu, tránh hoàn toàn vấn đề!
RhysW

Câu hỏi duy nhất của tôi là: Tôi nên sử dụng một con kiến ​​lớn như thế nào? (+1 BTW).
Peter K.

15
+1 cho cách phát âm chính xác của pas pas . (Và phần còn lại của câu trả lời.)
Blrfl

1
@PeterK., Đây là một trong số ít trường hợp phát triển phần mềm, cùng với màn hình, RAM và ổ đĩa, nơi IS lớn hơn tốt hơn.
John R. Strohm

16

Nếu bạn đang ở trong chuỗi công cụ ms. Nghiên cứu của bà đã tạo ra một công cụ sẽ buộc các can thiệp mới cho mỗi lần chạy và có thể tạo lại các lần chạy thất bại được gọi là cờ vua .

đây là một video cho thấy nó được sử dụng.


5
Điều đó có vẻ ấn tượng; Tôi sẽ phải tìm thời gian để thử nó vào một lúc nào đó.
Dan Neely

16

Công cụ tốt nhất mà tôi biết cho các loại vấn đề này là một phần mở rộng của Valgrind có tên Helgrind .

Về cơ bản Valgrind mô phỏng một bộ xử lý ảo và chạy nhị phân (chưa sửa đổi) của bạn trên đầu của nó, để nó có thể kiểm tra mọi truy cập duy nhất vào bộ nhớ. Sử dụng khung đó, hệ thống đồng hồ Helgrind gọi để suy luận khi quyền truy cập vào một biến được chia sẻ không được bảo vệ đúng cách bởi một cơ chế loại trừ lẫn nhau. Bằng cách đó, nó có thể phát hiện một điều kiện chủng tộc lý thuyết ngay cả khi nó không thực sự xảy ra.

Intel bán một công cụ rất giống là Intel Inspector .

Những công cụ này cho kết quả tuyệt vời nhưng chương trình của bạn sẽ chậm hơn đáng kể trong quá trình phân tích.


1
Valgrind vẫn là công cụ chỉ * nix?
Dan Neely

1
Có, Linux, MacOSX, android và một số BSD: valgrind.org/info/pl platforms.html
Julien

1
ThreadSanitizer là một công cụ tương tự. Nó hoạt động khác với Helgrind, điều này mang lại cho nó lợi thế là nhanh hơn nhiều, nhưng đòi hỏi phải tích hợp vào chuỗi công cụ.
Sebastian Redl

7

Phơi bày một lỗi đa luồng đòi hỏi buộc các luồng thực thi khác nhau phải thực hiện các bước của chúng theo một thứ tự xen kẽ cụ thể. Thông thường, điều này khó thực hiện nếu không gỡ lỗi thủ công hoặc thao tác mã để có được một số "xử lý" để kiểm soát sự xen kẽ này. Nhưng việc thay đổi mã hành xử không thể đoán trước thường sẽ ảnh hưởng đến sự khó lường đó, vì vậy điều này rất khó để tự động hóa.

Một mẹo hay được Jaroslav Tulach mô tả trong Thiết kế API thực tế : nếu bạn có câu lệnh ghi nhật ký trong mã đang được đề cập, hãy thao túng người tiêu dùng của các câu lệnh ghi nhật ký đó (ví dụ: thiết bị đầu cuối giả được chèn) để nó chấp nhận các thông điệp nhật ký riêng lẻ đặt hàng dựa trên nội dung của họ. Điều này cho phép bạn kiểm soát các bước xen kẽ trong các luồng khác nhau mà không phải thêm bất cứ điều gì vào mã sản xuất chưa có ở đó.


2
Tôi đã thực hiện tương tự trước khi sử dụng kho lưu trữ được tiêm để ngủ các luồng gọi nó theo thứ tự cụ thể để buộc xen kẽ tôi muốn. Có mã được viết, tôi nghiêng về câu trả lời của +1 @ John ở trên. Nghiêm túc mà nói, công cụ này rất đau đớn để sử dụng chính xác, và vẫn chỉ đưa ra những đảm bảo đoán tốt nhất bởi vì có thể có một chút xen kẽ với kết quả khác nhau; cách tiếp cận tốt hơn là chỉ cần loại bỏ tất cả các điều kiện chủng tộc có thể thông qua phân tích tĩnh và hoặc mã hóa cẩn thận cho bất kỳ và tất cả các trạng thái được chia sẻ
Jimmy Hoffa

6

Không có cách nào để chắc chắn tuyệt đối các loại hành vi không xác định (trong điều kiện chủng tộc cụ thể) không tồn tại.

Tuy nhiên, có một số công cụ hiển thị một số lượng tốt các tình huống như vậy. Bạn có thể chứng minh rằng hiện tại có một vấn đề với các công cụ như vậy, mặc dù bạn không thể chứng minh rằng sửa chữa của mình là hợp lệ.

Một số công cụ thú vị cho mục đích này:

Valgrind là một công cụ kiểm tra bộ nhớ. Nó tìm thấy rò rỉ bộ nhớ, đọc bộ nhớ chưa được khởi tạo, sử dụng các con trỏ lơ lửng và truy cập ngoài giới hạn.

Helgrind là một công cụ kiểm tra an toàn chủ đề. Nó tìm thấy điều kiện chủng tộc.

Cả hai đều hoạt động bằng thiết bị động, tức là chúng đưa chương trình của bạn nguyên trạng và thực thi nó trong môi trường ảo hóa. Điều này làm cho chúng không cố ý, nhưng chậm.

UBSan là một trình kiểm tra hành vi không xác định. Nó tìm thấy các trường hợp khác nhau của hành vi không xác định C và C ++, chẳng hạn như tràn số nguyên, dịch chuyển ngoài phạm vi và các công cụ tương tự.

MSan là một công cụ kiểm tra bộ nhớ. Nó có mục tiêu tương tự như Valgrind.

TSan là một kiểm tra an toàn chủ đề. Nó có mục tiêu tương tự như Helgrind.

Ba cái này được tích hợp vào trình biên dịch Clang và tạo mã tại thời điểm biên dịch. Điều này có nghĩa là bạn cần tích hợp chúng vào quá trình xây dựng của mình (cụ thể là bạn phải biên dịch với Clang), điều này khiến chúng khó thiết lập ban đầu hơn * xay, nhưng mặt khác chúng có chi phí thời gian chạy thấp hơn nhiều.

Tất cả các công cụ tôi liệt kê đều hoạt động trên Linux và một số trong số chúng trên MacOS. Tôi không nghĩ rằng bất kỳ công việc nào trên Windows đáng tin cậy.


1

Có vẻ như hầu hết các câu trả lời ở đây đều nhầm câu hỏi này là "làm thế nào để tôi tự động phát hiện các điều kiện cuộc đua?" khi câu hỏi thực sự là "làm thế nào để tôi tái tạo các điều kiện chủng tộc trong thử nghiệm khi tôi tìm thấy chúng?"

Cách thực hiện là giới thiệu đồng bộ hóa trong mã của bạn chỉ được sử dụng để thử nghiệm. Ví dụ: nếu điều kiện cuộc đua xảy ra khi Sự kiện X xảy ra ở giữa Sự kiện A và Sự kiện B, thì để kiểm tra ứng dụng của bạn, hãy viết một số mã chờ Sự kiện X xảy ra sau khi Sự kiện A xảy ra. Bạn có thể sẽ cần một số cách để các bài kiểm tra của bạn nói với ứng dụng của bạn để nói với nó ("hey tôi đang thử nghiệm điều này, vì vậy hãy chờ sự kiện này tại địa điểm này").

Tôi đang sử dụng node.js và mongo, trong đó một số hành động liên quan đến việc tạo dữ liệu nhất quán trong nhiều bộ sưu tập. Trong những trường hợp này, các thử nghiệm đơn vị của tôi sẽ thực hiện cuộc gọi đến ứng dụng để thông báo cho nó "thiết lập chờ sự kiện X" và khi ứng dụng đã thiết lập, thử nghiệm cho sự kiện X sẽ chạy và các thử nghiệm sau đó sẽ cho biết ứng dụng ("tôi đã hoàn thành với sự chờ đợi của Sự kiện X") vì vậy các thử nghiệm còn lại sẽ chạy bình thường.

Câu trả lời ở đây giải thích loại chi tiết này trong bối cảnh của python: https://stackoverflow.com/questions/19602535/how-can-i-reproduce-the-race-conditions-in-this-python-code- đáng tin cậy

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.