Hacker News

Հասկանալով Std:Shared_mutex C++17-ից

Մեկնաբանություններ

2 min read Via www.cppstories.com

Mewayz Team

Editorial Team

Hacker News

Հասկանալով std::shared_mutex C++17-ից

std::shared_mutex, որը ներկայացվել է C++17-ում, համաժամացման պրիմիտիվ է, որը թույլ է տալիս մի քանի շղթաներին միաժամանակ պահել ընդհանուր (կարդալու) կողպեքները՝ միաժամանակ ապահովելով գրելու գործողությունների բացառիկ մուտք: Այն լուծում է ժամանակակից C++-ի ամենասովորական համաժամանակյա մարտահրավերներից մեկը՝ ծրագրավորողներին տալով ընթերցող-գրողի կողպումն իրականացնելու մաքուր, ստանդարտ եղանակ՝ առանց երրորդ կողմի գրադարանների կամ հարթակի հատուկ API-ների հասնելու:

Ի՞նչ է կոնկրետ std::shared_mutex և ինչու է այն ավելացվել C++17-ում:

Մինչ C++17-ը, ծրագրավորողները, ովքեր կարիք ունեին ընթերցող-գրողի իմաստաբանության, պետք է ապավինեին հարթակին հատուկ լուծումներին, ինչպիսիք են pthread_rwlock_t-ը POSIX համակարգերում կամ SRWLOCK-ը Windows-ում, կամ կօգտագործեին երրորդ կողմի գրադարաններ, ինչպիսին է Boost-ը: C++17 ստանդարտ կոմիտեն ճանաչեց այս բացը և ներմուծեց std::shared_mutex վերնագրում՝ այն ուղղակիորեն լուծելու համար:

Հիմնական գաղափարը պարզ է. իրական աշխարհի շատ ծրագրերում տվյալները շատ ավելի հաճախ են կարդում, քան գրված են: Ստանդարտ std::mutex սերիականացնում է բոլոր մուտքերը՝ ներառված ընթերցումները, ինչը անհարկի խոչընդոտներ է ստեղծում: std::shared_mutex վերացնում է այդ սահմանափակումը` տարբերակելով երկու կողպման ռեժիմները.

  • Համօգտագործվող (կարդալ) կողպեք — ձեռք է բերվել lock_shared()-ի միջոցով; մի քանի շղթաները կարող են միաժամանակ պահել այն, ինչը այն դարձնում է իդեալական միաժամանակյա ընթերցումների համար:
  • Բացառիկ (գրելու) կողպեք — ձեռք է բերվել lock()-ի միջոցով; միայն մեկ շարանը կարող է միաժամանակ պահել սա, և այն պահելու ընթացքում չի թույլատրվում ընդհանուր կողպեքներ:
  • std::shared_lock — RAII փաթաթան, որը կանչում է lock_shared() շինարարության ժամանակ և unlock_shared() ոչնչացման ժամանակ՝ կանխելով ռեսուրսների արտահոսքը:
  • std::unique_lock / std::lock_guard — օգտագործվում է բացառիկ ռեժիմով՝ ապահովելով գրելու գործողությունները լիովին պաշտպանված և անվտանգ բացառությունների համար:

Այս երկռեժիմ դիզայնը դարձնում է std::shared_mutex-ը բնական պիտանի այնպիսի սցենարների համար, ինչպիսիք են քեշերը, կազմաձևման գրանցամատյանները և ցանկացած տվյալների կառուցվածք, որտեղ ընթերցումները գերակշռում են աշխատանքի ծանրաբեռնվածության վրա:

Ինչպե՞ս եք օգտագործում std::shared_mutex-ը ռեալ կոդում՝ մեկնաբանություններով:

Մեկնաբանությունները կոդի մեջ, որն օգտագործում է std::shared_mutex, հատկապես արժեքավոր են, քանի որ համաժամանակյա տրամաբանությունը բավականին դժվար է պատճառաբանել: Լավ տեղադրված մեկնաբանությունները պարզաբանում են ինչու ընտրվել է որոշակի կողպեքի տեսակ, ինչը կտրուկ նվազեցնում է ապագա սպասարկողների կողմից տվյալների մրցավազքի պատահական ներմուծման ռիսկը: Ահա տիպիկ օրինակ՝

#include 
#include 
#include 

դաս ConfigRegistry {
    փոփոխվող std::shared_mutex mtx_; // պաշտպանում է ստորև ներկայացված քարտեզը
    std::unordered_map data_;

հանրային:
    // Կարդալ ուղի. մի քանի շղթաներ կարող են միաժամանակ զանգահարել սա
    std::string ստանալ(const std::string& key) const {
        std::shared_lock lock (mtx_); // համօգտագործվող կողպեք — անվտանգ միաժամանակյա ընթերցումների համար
        auto it = data_.find(key);
        վերադարձնել այն != data_.end() ? it-> second : "";
    }

    // Գրելու ուղի. պահանջվում է բացառիկ մուտք
    void set (const std::string& key, const std::string& val) {
        std::unique_lock lock (mtx_); // բացառիկ կողպեք — արգելափակում է բոլոր ընթերցողներին
        տվյալների_[բանալի] = val;
    }
};

Ուշադրություն դարձրեք, թե ինչպես են մեկնաբանությունները բացատրում կողպեքի յուրաքանչյուր ընտրության մտադրությունը, այլ ոչ թե պարզապես վերափոխելու, թե ինչ է անում կոդը: Սա է ոսկե ստանդարտը. մեկնաբանությունները պետք է պատասխանեն ինչու, ոչ թե ինչ: Mutex-ի փոփոխելի հիմնաբառը թույլ է տալիս get()-ին հայտարարել const, մինչդեռ կարող է կողպել, ընդհանուր և բառապաշար օրինաչափություն:

Հիմնական պատկերացում. Միշտ օգտագործեք RAII կողպեքի փաթաթանները (std::shared_lock, std::unique_lock) std::shared_mutex-ի հետ — երբեք մի զանգահարեք lock() ձեռքով () (code>): Բացառությունների առկայության դեպքում ձեռքով կողպումը երաշխավորված ճանապարհ է դեպի փակուղիներ և չսահմանված վարքագիծ:

Որո՞նք են ընդհանուր որոգայթները std::shared_mutex-ի հետ աշխատելիս:

Նույնիսկ հստակ մեկնաբանություններով և բարի մտադրություններով, std::shared_mutex-ն ունի նուրբ թակարդներ, որոնք գրավում են փորձառու ծրագրավորողներին: Ամենավտանգավորը կողպեքի արդիականացումն է. չկա ներկառուցված միջոց՝ թարմացնելու ընդհանուր կողպեքը բացառիկ կողպեքի՝ առանց այն նախապես բացելու: Դա անելու փորձն առանց արձակելու ստեղծում է ակնթարթային փակուղի, քանի որ շարանը պահում է ընդհանուր կողպեքը, մինչ սպասում է բացառիկ կողպեքին, որը երբեք չի կարող տրվել, քանի դեռ որևէ ընդհանուր կողպեք գոյություն ունի, ներառյալ այն, որը պահում է:

💡 DID YOU KNOW?

Mewayz replaces 8+ business tools in one platform

CRM · Invoicing · HR · Projects · Booking · eCommerce · POS · Analytics. Free forever plan available.

Start Free →

Մյուս տարածված սխալը սխալ հատիկավորումը պաշտպանելն է: Մշակողները երբեմն չափազանց լայն են կողպում, խախտելով ընթերցող-գրող օրինաչափության նպատակը, կամ չափազանց նեղ՝ թողնելով պատուհանները, որտեղ ինվարիանտները խախտվում են երկու առանձին կողպեքների միջև: Մեկնաբանությունները, որոնք նկարագրում են անփոփոխությունը պաշտպանված է, այլ ոչ թե պարզապես փոփոխականը կողպված է, օգնում են թիմերին մտածելու ճիշտության մասին կոդի վերանայման ժամանակ:

Կատարումը կարող է նաև զարմացնել ձեզ: Բազմաթիվ գրողներ ունեցող համակարգերում std::shared_mutex իրականում կարող է ավելի վատ գործել, քան պարզ std::mutex՝ հաշվի առնելով լրացուցիչ հաշվապահական ծախսերը: Միշտ պրոֆիլը նախքան ենթադրելը, որ ընթերցող-գրողի կողպումը զուտ շահում է:

Ինչպե՞ս է std::shared_mutex համեմատվում std::mutex-ի և այլ այլընտրանքների հետ:

std::mutex ավելի պարզ է, ավելի արագ է ձեռք բերվում, երբ վիճաբանությունը ցածր է, և տեղին է, երբ ընթերցումները և գրերը տեղի են ունենում մոտավորապես հավասար հաճախականությամբ: std::shared_mutex փայլում է, երբ ընթերցումները զգալիորեն գերազանցում են գրություններին. 10:1 կամ ավելի բարձր հարաբերակցությունը ողջամիտ կանոն է նախքան անջատիչը դիտարկելը:

C++14-ը ներկայացրեց std::shared_timed_mutex, որն ավելացնում է try_lock_shared_for() և try_lock_shared_until() ժամանակային փորձերի համար: C++17-ի std::shared_mutex-ը թողնում է ժամանակային տարբերակները ավելի նիհար իրականացման համար: Եթե Ձեզ անհրաժեշտ է ժամանակավոր կողպում ընդհանուր ուղու վրա, std::shared_timed_mutex մնում է հասանելի, և երկու տեսակներն էլ լիովին ստանդարտ են:

Առանց կողպման այլընտրանքների համար std::atomic-ը զուգակցված հիշողության զգույշ պատվիրման հետ երբեմն կարող է ամբողջությամբ փոխարինել mutex-ին պարզ դրոշակների կամ հաշվիչների համար, սակայն տվյալների բարդ կառուցվածքների համար std::shared_mutex մնում է ստանդարտ գրադարանի ամենաընթեռնելի և պահպանվող լուծումը:

Հաճախակի տրվող հարցեր

Կարո՞ղ է std::shared_mutex սովամահություն առաջացնել:

Այո, կարող է: Եթե ​​ընդհանուր կողպեքի նոր սեփականատերերը շարունակաբար ժամանում են, բացառիկ կողպման հայցողը կարող է անվերջ սպասել՝ դասական գրողների սովի խնդիր: C++ ստանդարտը չի պահանջում կոնկրետ արդարության քաղաքականություն, ուստի վարքագիծը կախված է իրականացումից: Գործնականում գրադարանների ստանդարտ ներդրումներից շատերը առաջնահերթություն են տալիս սպասող բացառիկ կողպեքներին, երբ դրանք հերթագրվում են, բայց դուք պետք է ստուգեք դա ձեր հատուկ գործիքների շղթայի և հարթակի համար, եթե արտադրության մեջ սովը մտահոգիչ է:

Արդյո՞ք std::shared_mutex անվտանգ է օգտագործել std::condition_variable-ի հետ:

std::condition_variable-ը պահանջում է std::unique_lock, ուստի այն ուղղակիորեն համատեղելի չէ std::shared_mutex-ի հետ: Եթե ձեզ անհրաժեշտ է սպասել մի պայմանի, երբ պահում եք ընդհանուր mutex, օգտագործեք std::condition_variable_any, որն աշխատում է ցանկացած BasicLockable տեսակի հետ, ներառյալ std::shared_mutex՝ զուգակցված std::shared_lock-ի հետ:

Ավելացնե՞մ մեկնաբանություններ ամեն անգամ, երբ օգտագործում եմ std::shared_mutex:

Առնվազն մեկնաբանեք mutex-ի հայտարարությունը` նկարագրելու համար, թե ինչ տվյալներ է այն պաշտպանում և ինվարիանտները, որոնք պահպանում է: Յուրաքանչյուր կողպման վայրում հակիրճ մեկնաբանություն, որը բացատրում է, թե ինչու է ընտրվել համօգտագործվող և բացառիկ հասանելիությունը, զգալի արժեք է ավելացնում կոդերի վերանայողների և ապագա սպասարկողների համար: Համաժամանակյա վրիպակներն ամենադժվարներից են վերարտադրելու և շտկելու համար, ուստի հստակ, ճշգրիտ մեկնաբանություններում ներդրումները բազմապատիկ շահաբաժիններ են տալիս:


Բարդ համակարգերի կառավարումը, լինի դա միաժամանակ C++ կոդ, թե ամբողջ բիզնես գործողություն, պահանջում է ճիշտ գործիքներ և հստակ կառուցվածք: Mewayz-ը-ը 207 մոդուլից բաղկացած բիզնես ՕՀ-ն է, որին վստահում են ավելի քան 138,000 օգտատերեր, որոնք նույն պարզությունն են բերում մարքեթինգի, CRM-ի, էլեկտրոնային առևտրի, վերլուծության և այլնի մեջ, բոլորը մեկ հարթակում՝ սկսած ամսական ընդամենը 19 դոլարից: Դադարեցրեք տասնյակ անջատված գործիքների ձեռնածությունը և սկսեք ձեր բիզնեսը վարել լավ մշակված ծրագրաշարի ճշգրտությամբ: Փորձեք Mewayz-ն այսօր app.mewayz.com-ում և տեսեք, թե ինչպես է միասնական համակարգը փոխում ձեր թիմի աշխատանքը:

:

Try Mewayz Free

All-in-one platform for CRM, invoicing, projects, HR & more. No credit card required.

Start managing your business smarter today

Join 30,000+ businesses. Free forever plan · No credit card required.

Ready to put this into practice?

Join 30,000+ businesses using Mewayz. Free forever plan — no credit card required.

Start Free Trial →

Ready to take action?

Start your free Mewayz trial today

All-in-one business platform. No credit card required.

Start Free →

14-day free trial · No credit card · Cancel anytime