Мазмунга өтүү

Атомдук операциялар жана эстутум модели

Сабактын башталышы

Атомдук операциялар жана эстутум модели

Маалыматты агымдардын ортосунда кулпусуз, туура бөлүшүү

Негизги идея: Эки агым бир өзгөрмөгө кайрылып, эң аз дегенде бири жазганда, кадимки окуу/жазуу маалымат жарышын (data race) пайда кылат, а C++ тилинде маалымат жарышы жөн гана туура эмес маани эмес, аныкталбаган жүрүм-турум болуп саналат. 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 менен корголгон маалымат да жарышпайт - кулпу тартипти берет.

Бул сабакты YourAIZone платформасында улантыңыз

Толук сабакта — толук түшүндүрмө, чыгарылган мисалдар, көп кездешкен каталар, заматта текшерилүүчү тесттер жана ЖИ-репетитор. Конок катары дароо баштаңыз же прогрессти сактоо үчүн аккаунт түзүңүз.

Толук сабакта

  • Толук түшүндүрмө
  • Чыгарылган мисалдар
  • Көп кездешкен каталар жана алардан кантип качуу керек
  • Тест суроолору: 15
  • Тема боюнча суроолорго жооп берген ЖИ-репетитор
  • Окуучу, ата-эне жана мугалим үчүн прогрессти көзөмөлдөө