2009-02-04 7 views
8

Biến 'boolean' có an toàn để đọc và viết từ bất kỳ chuỗi nào không? Tôi đã nhìn thấy một số tài liệu tham khảo nhóm tin để nói rằng họ đang có. Có bất kỳ loại dữ liệu nào khác không? Sẽ có một danh sách tất cả các kiểu dữ liệu có thể được đọc một cách an toàn từ bất kỳ chủ đề nào và một danh sách khác cũng có thể được viết một cách an toàn vào bất kỳ chủ đề nào mà không cần phải sử dụng. với các phương thức đồng bộ hóa khác nhau.Danh sách các kiểu dữ liệu Delphi có hoạt động đọc/ghi 'thread-safe'?

Trả lời

7

Xin lưu ý rằng bạn có thể tạo bản chất mọi thứ trong delphi unthreadsafe. Trong khi những người khác đề cập đến vấn đề liên kết trên boolean này trong một cách ẩn các vấn đề thực sự.

Có, bạn có thể đọc boolean trong bất kỳ chuỗi nào và ghi vào boolean trong bất kỳ chuỗi nào nếu được căn chỉnh chính xác. Nhưng đọc từ một boolean bạn thay đổi không nhất thiết phải là "thread an toàn" anyway. Giả sử bạn có boolean bạn đặt thành true khi bạn đã cập nhật một số để chuỗi khác đọc số.

if NumberUpdated then 
begin 
    LocalNumber = TheNumber; 
end; 

Do tối ưu hóa bộ xử lý làm TheNumber có thể được đọc trước NumberUpdated được đọc, do đó bạn có thể nhận được giá trị cũ của TheNumber dù cho bạn cập nhật NumberUpdated ngoái.

Aka, mã của bạn có thể trở thành:

temp = TheNumber; 
if NumberUpdated the 
begin 
    LocalNumber = temp; 
end; 

IMHO, một nguyên tắc cơ bản của ngón tay cái:
". Đọc được an toàn chủ đề viết không phải là thread an toàn"
Vì vậy, nếu bạn định viết bảo vệ dữ liệu với đồng bộ hóa ở mọi nơi bạn đọc giá trị trong khi ghi có thể có khả năng xảy ra.
Mặt khác, nếu bạn chỉ đọc và viết một giá trị trong một chuỗi, thì đó là chuỗi an toàn. Vì vậy, bạn có thể thực hiện một đoạn văn bản lớn ở một vị trí tạm thời, sau đó đồng bộ hóa bản cập nhật dữ liệu ứng dụng.

Tiền thưởng làm phiền:

VCL không phải là chủ đề an toàn. Giữ tất cả các sửa đổi của ui công cụ trong chủ đề chính. Giữ tất cả các công cụ ui trong chuỗi chính.

Nhiều chức năng không phải là chủ đề an toàn, trong khi các hàm khác thường phụ thuộc vào các lệnh gọi winapi cơ bản.

Tôi không nghĩ rằng "danh sách" sẽ hữu ích vì "chuỗi an toàn" có thể có nghĩa là nhiều thứ.

+0

+1, điểm rất tốt. Đối với bất kỳ ai quan tâm, hãy xem ví dụ http://en.wikipedia.org/wiki/Memory_barrier và thông tin được liên kết. – mghie

5

Trên kiến ​​trúc 32 bit, chỉ các loại dữ liệu 32 bit hoặc ít được căn chỉnh phù hợp mới được xem là nguyên tử. Giá trị 32 bit phải được căn chỉnh 4 (địa chỉ của dữ liệu phải chia đều cho bốn). Bạn có lẽ sẽ không chạy vào xen kẽ ở mức độ chặt chẽ như vậy, nhưng về mặt lý thuyết bạn có thể có đôi, Int64 hoặc mở rộng không nguyên tử viết.

+0

Trong một thời gian rất dài, việc đọc/ghi 64 bit được căn chỉnh là nguyên tử trên phần cứng x86, ngay cả ở chế độ 32 bit –

+0

. Tôi đã từng chứng minh điều này cho bản thân mình với một số chủ đề rất ngắn mà rèn phù hợp dữ liệu phù hợp với viết, trong khi các chủ đề khác đã cố gắng để đọc chúng. Các độc giả được mã hóa để tăng các ngoại lệ khi các giá trị được đọc không nằm trong một tập hợp các giá trị mà các nhà văn đang viết. –

7

Đây không phải là câu hỏi về các kiểu dữ liệu được an toàn theo luồng, nhưng đó là câu hỏi về những gì bạn làm với chúng. Nếu không khóa, không có thao tác nào là an toàn thread liên quan đến việc tải một giá trị, sau đó thay đổi nó, sau đó viết lại: tăng hoặc giảm số, xóa hoặc thiết lập một phần tử trong tập hợp - tất cả chúng đều không an toàn.

Có một số chức năng cho phép các hoạt động nguyên tử: gia tăng đan xen, giảm liên tục và trao đổi liên khóa. Đây là một khái niệm phổ biến, không có gì đặc trưng cho Windows, x86 hoặc Delphi. Đối với Delphi, bạn có thể sử dụng các hàm InterlockedFoo() của API Windows, có một số hàm bao quanh các hàm đó. Hoặc viết cho riêng bạn. Các hàm hoạt động trên các số nguyên, vì vậy bạn có thể tăng số nguyên tử, giảm và trao đổi các số nguyên (32 bit) với chúng.

Bạn cũng có thể sử dụng các trình tạo tiền tố và tiền tố với tiền tố khóa.

Để biết thêm thông tin, xem thêm this StackOverflow câu hỏi.

0

Mã Indy chứa một số nguyên tử/thread kiểu dữ liệu an toàn trong IdThreadSafe.pas:

  • TIdThreadSafeInteger
  • TIdThreadSafeBoolean
  • TIdThreadSafeString
  • TIdThreadSafeStringList và một số chi tiết ...
1

Xử lý đa lõi RISC và lõi c riêng biệt bộ nhớ nhức nhối là trong sự pha trộn của một bộ vi xử lý hiện đại, không còn trường hợp bất kỳ ngôn ngữ cấp cao 'tầm thường' nào đọc hoặc viết cấu trúc (hoặc cho vấn đề đó nhiều lần một hướng dẫn lắp ráp nguyên tử 8086 'nguyên tử')) có thể được coi là nguyên tử. Thật vậy, trừ khi một hướng dẫn lắp ráp được thiết kế đặc biệt để là nguyên tử, nó có lẽ không phải là nguyên tử - và bao gồm hầu hết các cơ chế cho bộ nhớ đọc. Ngay cả một số nguyên dài đọc ở cấp độ assembler cũng có thể bị hỏng bằng cách ghi đồng thời từ một lõi bộ xử lý khác đang chia sẻ cùng một bộ nhớ và sử dụng các hành động cập nhật bộ đệm không đồng bộ ở cấp bộ xử lý RISC. Hãy nhớ rằng trên một bộ xử lý bao gồm nhiều lõi RISC, ngay cả các hướng dẫn ngôn ngữ lắp ráp chỉ có hiệu quả các lệnh mã "cao cấp" hơn! Bạn không bao giờ thực sự biết cách chúng được thực hiện ở mức bit như thế nào, và nó có thể không hoàn toàn là những gì bạn mong đợi nếu bạn đang đọc một sổ tay lắp ráp 8086 (một lõi) cũ. Windows cung cấp các toán tử nguyên tử tương thích với hệ thống nguyên gốc và bạn sẽ được khuyên sử dụng chúng hơn là tạo ra các giả định cơ bản về các hoạt động nguyên tử.

Tại sao lại sử dụng toán tử Windows? Bởi vì một trong những thứ đầu tiên mà Windows thực hiện là thiết lập máy tính đang chạy. Một trong những khía cạnh quan trọng nó đảm bảo nó được đúng là những gì hoạt động nguyên tử có và làm thế nào họ sẽ làm việc. Nếu bạn muốn mã của bạn hoạt động tốt trong tương lai trên bất kỳ bộ vi xử lý nào trong tương lai, bạn có thể sao chép (và liên tục cập nhật) tất cả nỗ lực này trong mã của riêng bạn hoặc bạn có thể sử dụng thực tế là Windows đã làm tất cả khi khởi động. Sau đó nó kết hợp mã cần thiết vào API của nó khi chạy.

Đọc các trang MSDN về các hoạt động nguyên tử. API Windows sẽ hiển thị những điều này cho bạn. Đôi khi họ có vẻ có vẻ vụng về hoặc vụng về - nhưng họ là bằng chứng trong tương lai và họ sẽ luôn làm việc chính xác như đã nói trên tin.

Làm cách nào để biết điều này? Vâng, bởi vì nếu họ không - sau đó bạn sẽ không thể chạy Windows. Ngừng hẳn. Đừng bận tâm khi chạy mã của riêng bạn.

Bất cứ khi nào bạn viết mã, bạn nên hiểu rõ Parsimony và xem xét Occam's razor. Nói cách khác, nếu Windows đã thực hiện nó, và mã của bạn cần Windows để chạy, thì hãy sử dụng những gì Windows đã làm, thay vì thử nhiều giải pháp giả định thay thế và ngày càng phức tạp mà có thể có hoặc không hoạt động. Làm bất cứ điều gì khác chỉ là một sự lãng phí thời gian của bạn (trừ khi tất nhiên đó là những gì bạn đang ở).