Melaksanakan Kaunter ABA dengan C 11 CAS
Masalah ABA berlaku apabila nilai lokasi memori diubah suai dua kali, dengan pengubahsuaian selang yang menetapkan ia kembali kepada nilai asalnya. Ini boleh menipu utas yang bergantung pada operasi banding-dan-tukar atom (CAS) untuk mempercayai bahawa nilai tidak berubah, padahal nilai itu sebenarnya telah berubah.
Untuk mengelakkan masalah ABA, penyelesaian biasa ialah mencipta pembilang yang bertambah dengan setiap perubahan ke lokasi memori. Pembilang ini ditambah secara atom bersama-sama dengan perubahan, supaya operasi CAS boleh menyemak sama ada pembilang juga telah berubah sejak operasi terakhir.
Dalam C 11, fungsi std::atomic_compare_exchange_weak menyediakan operasi CAS atom. Walau bagaimanapun, ia tidak membenarkan pengubahsuaian serentak berbilang pembolehubah, seperti nilai dan pembilang.
Untuk melaksanakan pembilang ABA dengan C 11 CAS, kita perlu menyimpan pembilang dan nilai dalam memori bersebelahan lokasi, supaya satu operasi CAS boleh mengemas kini kedua-dua nilai secara atom. Ini boleh dicapai menggunakan struct dengan dua ahli, di mana ahli pertama ialah nilai dan ahli kedua ialah pembilang:
struct Node { std::atomic<int> value; std::atomic<int> counter; };
Dengan struktur data ini, kita boleh menggunakan fungsi std::atomic_compare_exchange_weak untuk laksanakan pembilang ABA:
void modifyValue(Node& node, int newValue) { int expectedValue = node.value.load(std::memory_order_relaxed); int expectedCounter = node.counter.load(std::memory_order_relaxed); bool success; do { success = node.value.compare_exchange_weak(expectedValue, newValue, std::memory_order_acq_rel); success = node.counter.compare_exchange_weak(expectedCounter, expectedCounter + 1, std::memory_order_acq_rel); } while (!success); }
Dalam contoh ini, fungsi modifyValue mula-mula memuatkan nilai yang dijangkakan dan pembilang menggunakan std::memory_order_relaxed memory order, yang membolehkan nilai dibaca tidak teratur dan boleh menyebabkan koyak.
Fungsi std::atomic_compare_exchange_weak kemudiannya digunakan untuk membandingkan nilai yang dijangkakan dan pembilang dengan nilai semasa dalam lokasi ingatan. Jika nilai sepadan, nilai dan pembilang baharu akan ditulis ke lokasi menggunakan susunan memori std::memory_order_acq_rel, yang memastikan penulisan kelihatan kepada urutan lain selepas operasi selesai.
Jika nilai tidak sepadan, fungsi compare_exchange_weak gagal dan gelung dilaksanakan semula, memuatkan nilai dijangka dan pembilang terkini sebelum mencuba pertukaran atom sekali lagi.
Pelaksanaan ini memastikan pembilang dinaikkan secara atom dengan nilai, menghalang masalah ABA dan memastikan bahawa utas boleh bergantung dengan selamat pada ketekalan nilai.
Atas ialah kandungan terperinci Bagaimana untuk Melaksanakan Kaunter ABA dalam C 11 Menggunakan Banding-dan-Tukar Atom?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!