Điều kiện chủng tộc chắc chắn vẫn tồn tại ngay cả với cấu trúc dữ liệu chưa được chia sẻ. Hãy xem xét những điều sau đây:
B asks A for the currentCount
C asks A for the currentCount
B sends A (newDataB, currentCount + 1)
A stores newDataB at location currentCount+1
C sends A (newDataC, currentCount + 1)
A stores newDataC at currentCount + 1 (overwriting newDataB; race condition)
tình trạng đua này đòi hỏi nhà nước có thể thay đổi tư nhân ở A, nhưng không thể thay đổi cấu trúc dữ liệu được chia sẻ và thậm chí không đòi hỏi nhà nước có thể thay đổi trong B hoặc C. Không có gì là B hoặc C có thể làm gì để ngăn chặn điều kiện chủng tộc này mà không hiểu hợp đồng mà A đưa ra.
Ngay cả Haskell cũng có thể phải chịu đựng các điều kiện chủng tộc này ngay khi tiểu bang bước vào phương trình và trạng thái rất khó loại bỏ hoàn toàn khỏi hệ thống thực. Cuối cùng, bạn muốn chương trình của bạn tương tác với thực tế, và thực tế là trạng thái bình thường.Wikipedia cung cấp cho a helpful race condition example in Haskell sử dụng STM.
Tôi đồng ý rằng cấu trúc dữ liệu không thay đổi tốt có thể làm mọi thứ dễ dàng hơn (Go không thực sự có chúng). Các bản sao đột biến trao đổi một vấn đề cho người khác. Bạn không thể vô tình thay đổi dữ liệu của người khác. Mặt khác, bạn có thể nghĩ rằng rằng bạn đang thay đổi thực tế, khi bạn thực sự chỉ thay đổi một bản sao, dẫn đến một loại lỗi khác. Bạn phải hiểu hợp đồng theo cách nào đó.
Nhưng cuối cùng, Go có xu hướng theo lịch sử của C trên đồng thời: bạn tạo một số quy tắc quyền sở hữu cho mã của mình (như @ tux21b phiếu mua hàng) và đảm bảo bạn luôn theo dõi chúng. mọi việc đều tuyệt vời, và nếu bạn từng phạm sai lầm, thì rõ ràng đó là lỗi của bạn, không phải ngôn ngữ.
(Đừng hiểu sai, tôi thích Go, khá nhiều và thực sự cung cấp một số công cụ tốt để tạo sự đồng thời dễ dàng. Nó không cung cấp nhiều công cụ ngôn ngữ để giúp đồng thời chính xác. Điều đó nói rằng, câu trả lời của tux21b cung cấp rất nhiều lời khuyên tốt, và máy dò cuộc đua chắc chắn là một công cụ mạnh mẽ để giảm các điều kiện chủng tộc, nó không phải là một phần của ngôn ngữ, và nó là về thử nghiệm, chứ không phải chính xác; điều tương tự)
EDIT:. với câu hỏi về việc tại sao cấu trúc dữ liệu bất biến làm cho mọi việc dễ dàng hơn, đây là phần mở rộng của điểm ban đầu của bạn: tạo ra một hợp đồng mà nhiều bên không thay đổi dat cùng một cấu trúc. Nếu cấu trúc dữ liệu là không thay đổi, thì điều đó xuất hiện miễn phí…
Nhiều ngôn ngữ có tập hợp các lớp và lớp học không thay đổi phong phú. C++ cho phép bạn const
mọi thứ. Mục tiêu-C có các bộ sưu tập bất biến với các lớp con có thể thay đổi (tạo ra một tập các mẫu khác với const
). Scala có các phiên bản riêng biệt có thể thay đổi và bất biến của nhiều loại bộ sưu tập và thực tế phổ biến là sử dụng các phiên bản không thể thay đổi được. Tuyên bố bất biến trong một chữ ký phương pháp là một dấu hiệu quan trọng của hợp đồng.
Khi bạn vượt qua một []byte
thành goroutine, không có cách nào để biết từ mã cho dù goroutine có ý định sửa đổi lát hay không khi bạn có thể tự sửa đổi lát. Có một mẫu mới nổi, nhưng chúng giống như quyền sở hữu đối tượng C++ trước khi di chuyển ngữ nghĩa; rất nhiều cách tiếp cận tốt đẹp, nhưng không có cách nào để biết cái nào đang được sử dụng. Đó là một điều quan trọng mà mọi chương trình cần phải làm một cách chính xác, nhưng ngôn ngữ cho bạn không có công cụ tốt, và không có mô hình phổ quát được sử dụng bởi các nhà phát triển.
Điều kiện chủng tộc khó gỡ lỗi, cũng khó tránh được chúng. Tôi sẽ đề nghị suy nghĩ về các mô hình được mô tả ở đây bởi Rob Pike http://vimeo.com/49718712 khi anh ta đi qua các cấu trúc nhất định về cách các kênh và ngữ nghĩa CSP làm cho ứng dụng an toàn bằng thiết kế thay vì lo lắng về tất cả các vấn đề liên quan đến mutex. Tôi xin lỗi nếu điều này không trả lời câu hỏi của bạn nhưng tôi hy vọng nó sẽ mở ra nhiều cánh cửa hơn cho những ý tưởng mới. – ymg
Cảm ơn bạn đã liên kết. Đúng, điều kiện chủng tộc rất khó để ngăn chặn, nhưng thậm chí khó khăn hơn để gỡ lỗi! Tôi đoán một phiên bản bất biến của các bộ sưu tập sẽ làm giảm bớt vấn đề ở một mức độ nào đó, nhưng sau đó chúng tôi trở lại sân sau của chương trình chức năng. – tldr
Có _are_ các ngôn ngữ dựa trên bất biến/chức năng khác (chẳng hạn như F #), nhưng nó thực sự về phong cách. Bạn đúng về việc cần thêm bộ nhớ, nhưng thiết kế phù hợp có thể loại bỏ một số chi phí. Ví dụ, các mảng ghi trên sửa đổi có thể được thực hiện trong không gian 'n log n' (hoặc ít hơn đối với một số trường hợp tiềm năng) trung bình, chứ không phải là một' 2n' ngây thơ. Mặc dù hỗ trợ ngôn ngữ/trình tối ưu hóa có thể thực hiện một số điều điên rồ cho các ngôn ngữ được xây dựng ... –