Атомдук операциялар жана эстутум модели
Маалыматты агымдардын ортосунда кулпусуз, туура бөлүшүү
std::atomic<T> бөлүнгүс операцияларды берет (эч бир агым жарым жазылган маанини көрбөйт) жана, ошондой эле маанилүү, бир агымдын жазуулары башка агымга кайсы тартипте көрүнөрүн башкарууга мүмкүндүк берет. Бул тема эки жарымы жөнүндө тең: атомдуулук жана "көрүнөт" деген сөздү аныктаган эстутум модели жөнүндө.
- маалымат жарышы деген эмне жана эмне үчүн ал аныкталбаган жүрүм-турум экенин так айтуу;
std::atomic<T>колдонуу -load,store,exchange,fetch_add,compare_exchange;- happens-before байланышын жана ал жазууну кантип көрүнүктүү кыларын түшүндүрүү;
- интуиция деңгээлинде
seq_cst,acquire/releaseжанаrelaxedэстутум тартиптери жөнүндө ой жүгүртүү.
1. Маалымат жарышы - аныкталбаган жүрүм-турум
Маалымат жарышы эки агым бир эстутум жайына бир убакта кайрылганда, эң аз дегенде бир кайрылуу жазуу болуп, бул кайрылуулар эч кандай синхрондоштуруу менен иреттелбегенде пайда болот. C++ стандарты маалымат жарышы бар программа аныкталбаган жүрүм-турумга (UB) ээ дейт. Бул "эскирген маани окушуңуз мүмкүн" дегенден күчтүүрөөк: компилятор менен процессорго жарыш эч качан болбойт деп эсептөөгө уруксат берилет, ошондуктан жарыш "жыртылган" маани, жоголгон жаңылоо же ырааттуу мааниси жок оптимизацияны бере алат.
int counter = 0; // кадимки int, жалпы
void worker() {
for (int i = 0; i < 100000; ++i)
++counter; // окуу-өзгөртүү-жазуу, атомдук ЭМЕС -> ЖАРЫШ
}
// worker() иштеткен эки агым counter үчүн жарышат.
// Акыркы маани божомолсуз, программа - UB.
++counter бир кадамдай көрүнөт, бирок чындыгында үч: жүктөө, бирди кошуу, жазуу. Эки агым тең бир маанини жүктөп, экөө тең бирди кошуп, экөө тең жаза алат - ошентип эки инкремент бирге айланат. counter корголбогон int бойдон калтыруу - бул жөн гана туура эмес суммага коркунуч эмес; бул жарыш, а жарыштар - UB.
std::mutex менен корголгон маалымат да жарышпайт - кулпу тартипти берет.