Кіріспе

Бағдарламалық жасақтамадағы бір мезгілділікті басқару механизмі. Компьютерлік ғылымда бағдарламалық транзакциялық жад (STM) – бір мезгілді есептеуде ортақ жадқа қол жеткізуді басқару үшін дерекқорының транзакцияларына ұқсас бір мезгілділікті басқару механизмі. Бұл құлыптауға негізделген синхрондаудың баламасы. STM – аппараттық компонент ретінде емес, бағдарламалық жасақтамада іске асырылатын стратегия. Бұл жағдайда транзакция, кодтың бір бөлігі ортақ жадқа бірнеше оқу және жазу операцияларын орындағанда жүзеге асады. Бұл оқулар мен жазулар логикалық тұрғыдан бір сәтте болады; аралық күйлер басқа (сәтті аяқталған) транзакцияларға көрінбейді. Транзакцияларға аппараттық қолдау көрсету идеясы Том Найттың 1986 жылғы мақаласында туындады. Бұл идеяны Морис Герлихи және Дж. Элиот Б. Мосс танымал етті. 1995 жылы Нир Шавит пен Дэн Туиту бұл идеяны тек бағдарламалық транзакциялық жадқа (STM) қатысты кеңейтті. 2005 жылдан бері STM қарқынды зерттеулердің назарында болып келеді және практикалық іске асыруға қолдау артып келеді.

Өнер көрсету

Көптеген заманауи көп жіпті қолданбаларда қолданылатын құлыптау техникаларынан өзгеше, STM көбінесе өте оптимистік болады: бір жіп ортақ жадқа өзгерістер енгізуді аяқтайды, басқа жіптер не істеп тұрғанына қарамастан, барлық оқу және жазу амалдарын журналға тіркейді. Жазушының басқа ағымдағы операцияларға кері әсер етпеуін қамтамасыз ету жауапкершілігінен гөрі, бұл жауапкершілік оқырманға жүктеледі. Оқырман толық транзакцияны аяқтағаннан кейін, басқа жіптер оның бұрын қол жеткізген жадына бір мезгілде өзгерістер енгізбегенін тексереді. Бұл соңғы операция, онда транзакцияның өзгерістері тексеріледі және тексеру сәтті аяқталса, олар тұрақты болады, міндеттеме деп аталады. Транзакция кез келген уақытта тоқтатылуы мүмкін, бұл оның барлық бұрынғы өзгерістерін кері қайтаруға немесе жоюға әкеледі. Егер транзакция қарама-қайшылықты өзгерістерге байланысты міндеттемеге қол жеткізе алмаса, әдетте тоқтатылып, сәтті аяқталғанша басынан бастап қайта орындалады. Бұл оптимистік тәсілдің артықшылығы – жоғары параллелизм: ешбір жіп ресурстың қолжетімді болуын күтуге қажеті жоқ, және әртүрлі жіптер бір уақытта дерек құрылымының бөлек бөліктерін қауіпсіз түрде өзгерте алады, бұл бөліктер әдетте бір құлыппен қорғалады. Дегенмен, практикада STM жүйелері, процессорлардың аз санында (қолданбаға байланысты 1-ден 4-ке дейін) ұсақ түйірлі құлыптауға негізделген жүйелерге қарағанда өнімділік бойынша кемістіктерге тап болуы мүмкін. Бұл негізінен журналды жүргізуге байланысты қосымша шығындар мен транзакцияларды міндеттемеге жеткізуге жұмсалатын уақытқа байланысты. Тіпті осы жағдайда да өнімділік әдетте екі еседен аспайды. STM-ді жақтаушылар бұл кемшілікті STM-нің ұғымдық артықшылықтарымен толықтай ақталады деп санайды. Теориялық тұрғыдан алғанда, n бір мезгілдегі транзакциялардың ең нашар жағдайдағы кеңістіктік және уақыттық күрделілігі O(n) құрайды. Нақты қажеттіліктер жүзеге асыру ерекшеліктеріне байланысты (шығындарды болдырмау үшін транзакциялардың ертерек сәтсіздікке ұшырауына қол жеткізуге болады), бірақ бағдарламалық транзакциялық жадға қарағанда құлыптауға негізделген алгоритмдердің уақыт жағынан күрделілігі жақсырақ болатын сирек жағдайлар да болады.

Тұжырымдамалық артықшылықтар мен кемшіліктер

Орындау артықшылықтарынан басқа, STM көп тірісті бағдарламалардың түсінілуін жеңілдетеді және объектілер мен модульдер сияқты жоғары деңгейдегі абстракциялармен үйлесімді жұмыс істеу арқылы бағдарламаларды күтіп-ұстауды жеңілдетеді. Құлыптауға негізделген бағдарламалауда тәжірибеде жиі туындайтын бірнеше мәселе бар: Құлыптау кодтың қашық және көрінбейтін бөлімдеріндегі бір-бірімен байланысты операциялар мен жартылай орындалған операциялар туралы ойлауды қажет етеді, бұл өте қиын және қателерге бейім міндет. Құлыптау бағдарламалаушылардан тұйықталудың, тірі қамаудың және прогреске кедерес келтіретін басқа да мәселелердің алдын алу үшін құлыптау саясатын қабылдауды талап етеді. Мұндай саясат көбінесе ресми емес түрде сақталады және қателіктерге ұшырауы мүмкін, ал осы мәселелер туындағанда оларды қайта жасау және түзету өте қиын. Құлыптау басымдық инверсиясына әкелуі мүмкін, яғни жоғары басымдылыққа ие тіріс, қажетті ресурстың эксклюзивті құлпын ұстап тұрған төмен басымдылыққа ие тіріс күтуге мәжбүр болады. Керісінше, жад транзакциясының түсінігі әлдеқайда қарапайым, өйткені әрбір транзакция жеке тіріс есептеу ретінде қарастырылуы мүмкін. Тұйықталу және тірі қамау толығымен алдын алынады немесе сыртқы транзакция менеджерімен басқарылады; бағдарламашы мұндай мәселелер туралы алаңдаудың қажеті жоқ. Басымдық инверсиясы мәселесі әлі де туындауы мүмкін, бірақ жоғары басымдылыққа ие транзакциялар әлі міндеттеме алған жоқ, төмен басымдылыққа ие транзакцияларды тоқтатуы мүмкін. Дегенмен, транзакцияларды қайтадан орындау және тоқтату қажеттілігі олардың мінез-құлқына шектеулер қояды. Транзакция ішінде орындалатын кез келген операция идемпотентті болуы керек, өйткені транзакция қайтадан орындалуы мүмкін. Сонымен қатар, егер операция тоқтатылған жағдайда кері қайтару қажет болатын жанама әсерлерге ие болса, сәйкес кері операция қосылуы тиіс. Бұл көптеген кіріс/шығыс (I/O) операцияларын транзакциялар ішінде орындауды қиындатады немесе мүмкін емес етеді. Мұндай шектеулер әдетте қайталанбайтын операцияларды кезекке қоятын және транзакция сәтті аяқталғаннан кейін оларды орындайтын буферлер құру арқылы еңсеріледі. Haskell-де бұл шектеу деректер типі жүйесімен компиляция кезінде күшіне енгізіледі.

Композицияланатын операциялар

2005 жылы Тим Харрис, Саймон Марлоу, Саймон Пейтон Джонс және Морис Герлихи Concurrent Haskell-ге негізделген STM жүйесін сипаттады, ол кез келген атомдық операцияларды үлкен атомдық операцияларға біріктіруге мүмкіндік береді, бұл құлыптауға негізделген бағдарламалауда мүмкін емес, пайдалы ұғым. Авторлардың сөзін келтірейік: «Бәлкім, ең негізгі қарсылық [ ] – құлыптауға негізделген бағдарламалар біріктірілмейді: дұрыс фрагменттер біріктірілген кезде қате болуы мүмкін. Мысалы, thread safe insert және delete операциялары бар хэш-кестені қарастырайық. Енді t1 кестесінен бір A элементін өшіріп, оны t2 кестесіне енгізгіміз делік; бірақ аралық күй (екі кестеде де элемент жоқ) басқа жіптерге көрінбеуі керек. Егер хэш-кестені жүзеге асырушы осы қажеттілікті ескермесе, бұл талапты қанағаттандырудың жолы жоқ». [ ] Қысқасы, жеке-жеке дұрыс операцияларды (қосу, өшіру) үлкен дұрыс операцияларға біріктіруге болмайды. —Тим Харрис және т.б., «Біріктірілетін жад транзакциялары», 2-бөлім: Негізгі мәліметтер, 2-бет. STM-мен бұл мәселені шешу оңай: екі операцияны транзакцияға орау біріктірілген операцияны атомдық етеді. Бір ғана қиындық бар: компоненттік әдістердің іске асылу егжей-тегжейін білмейтін шалушыға операция сәтсіз аяқталса, оны қайта орындауға тырысу керек пе, әлде жоқ па, белгісіз. Оған жауап ретінде авторлар қайталап әрекет ету командасын ұсынды, ол сәтсіз транзакция жасаған транзакция журналын пайдаланып, қандай жад жасушаларын оқығанын анықтайды және осы жасушалардың бірі өзгерген кезде транзакцияны автоматты түрде қайталайды, себебі кем дегенде бір мән өзгермегенше транзакция басқаша әрекет етпейді деген логикаға сүйенеді. Авторлар сондай-ақ баламаларды біріктіру механизмін, orElse функциясын ұсынды. Ол бір транзакцияны орындайды және егер ол қайталап әрекет етсе, екінші транзакцияны орындайды. Егер екеуі де қайталап әрекет етсе, тиісті өзгеріс жасалғанша оларды қайтадан сынап көреді. Бұл мүмкіндік, Портативті Операциялық Жүйе Интерфейсі (POSIX) желілік таңдау шақыруы сияқты мүмкіндіктерге ұқсас, шалушыға бірнеше оқиғалардың кез келгеніне бір уақытта күтуге мүмкіндік береді. Ол сонымен қатар бағдарламалау интерфейстерін жеңілдетеді, мысалы, бұғаттау және бұғаттау емес операцияларды алмастырудың қарапайым механизмін ұсынады. Бұл схема Глазго Хаскелл компиляторында жүзеге асырылды.