Khi sử dụng bộ nhớ dùng chung, mỗi quá trình có thể chia vùng chia sẻ thành một vùng khác nhau trong không gian địa chỉ tương ứng. Điều này có nghĩa là khi lưu trữ con trỏ trong khu vực được chia sẻ, bạn cần phải store them as offsets khi bắt đầu khu vực được chia sẻ. Thật không may, điều này làm phức tạp việc sử dụng các hướng dẫn nguyên tử (ví dụ: nếu bạn đang cố viết một số lock free algorithm). Ví dụ: giả sử bạn có một loạt các nút được tính tham chiếu trong bộ nhớ dùng chung, được tạo bởi một người viết duy nhất. Các nhà văn định kỳ cập nhật một cách nguyên tử một con trỏ 'p' để trỏ đến một nút hợp lệ với số tham chiếu tích cực. Người đọc muốn viết nguyên tử thành 'p' bởi vì nó trỏ tới phần đầu của một nút (một cấu trúc) mà phần tử đầu tiên của nó là một số tham chiếu. Vì p luôn trỏ đến một nút hợp lệ, việc gia tăng số lượng ref là an toàn, và làm cho nó an toàn để dereference 'p' và truy cập các thành viên khác. Tuy nhiên, tất cả điều này chỉ hoạt động khi mọi thứ ở trong cùng một không gian địa chỉ. Nếu các nút và 'p' con trỏ được lưu trữ trong bộ nhớ chia sẻ, sau đó khách hàng phải chịu một điều kiện chủng tộc:Có thể lưu trữ con trỏ trong bộ nhớ dùng chung mà không sử dụng bù trừ không?
- x = đọc p
- y = x + bù đắp
- Tăng refcount tại y
Trong bước 2, p có thể thay đổi và x không còn trỏ đến nút hợp lệ nữa. Cách giải quyết duy nhất tôi có thể nghĩ là bằng cách nào đó buộc tất cả các quy trình phải đồng ý về nơi để ánh xạ bộ nhớ dùng chung, do đó con trỏ thực thay vì dời gốc có thể được lưu trữ trong vùng mmap'd. Có cách nào để làm điều đó? Tôi thấy MAP_FIXED trong tài liệu mmap, nhưng tôi không biết làm cách nào tôi có thể chọn một địa chỉ an toàn.
Chỉnh sửa: Sử dụng lắp ráp nội tuyến và tiền tố 'khóa' trên x86 có thể có thể tạo "giá trị gia tăng ptr với bù đắp Y theo giá trị Z"? Tùy chọn tương đương trên các kiến trúc khác? Đã không viết rất nhiều hội đồng, không biết nếu các hướng dẫn cần thiết tồn tại.
Nếu cmpxchg đã thực hiện đọc nguyên tử và viết nguyên tử, có phải 'khóa' cần thiết không? Hay điều đó đảm bảo rằng edi + edx được thực hiện một cách nguyên tử? Tôi đã từng thực sự sử dụng lắp ráp MIPS. –
Đảm bảo khóa truy cập nguyên tử vào bus bộ nhớ để lệnh khóa là cần thiết. Bạn cũng có thể sử dụng API InterlockedCompareExchange (kiểm tra MSDN để giải thích). Lúc đầu tải bộ nhớ 32 bit con trỏ như OldValue và hơn increment nó để có được NewValue, sau đó cố gắng để làm InterlockedCompareExchange. InterlockedCompareExchange (Destination + Offset, NewValue, OldValue) sẽ trả về giá trị so sánh nếu không giống với OldValue so với một số luồng khác đang trao đổi nó, vì vậy không có trao đổi nào được thực hiện và bạn phải lặp lại quy trình. –