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, ເປັນ synchronization primitive ທີ່ອະນຸຍາດໃຫ້ຫຼາຍ threads ພ້ອມກັນຖື locks ແບ່ງປັນ (ອ່ານ) ໃນຂະນະທີ່ຮັບປະກັນການເຂົ້າເຖິງສະເພາະສໍາລັບການດໍາເນີນງານການຂຽນ. ມັນແກ້ໄຂສິ່ງທ້າທາຍທີ່ພົບເລື້ອຍທີ່ສຸດໃນ C++ ສະໄໝໃໝ່ໂດຍການໃຫ້ນັກພັດທະນາເປັນວິທີທີ່ສະອາດ ແລະເປັນມາດຕະຖານເພື່ອປະຕິບັດການລັອກຕົວອ່ານໂດຍບໍ່ໄດ້ໄປຫາຫ້ອງສະໝຸດພາກສ່ວນທີສາມ ຫຼື APIs ສະເພາະຂອງແພລດຟອມ.

ແມ່ນຫຍັງຄື std::shared_mutex ແລະເປັນຫຍັງມັນຖືກເພີ່ມເຂົ້າໃນ C++17?

ກ່ອນ C++17, ຜູ້ພັດທະນາທີ່ຕ້ອງການຄວາມໝາຍຂອງຜູ້ອ່ານ-ນັກຂຽນຕ້ອງອາໄສການແກ້ໄຂບັນຫາສະເພາະຂອງເວທີເຊັ່ນ pthread_rwlock_t ໃນລະບົບ POSIX ຫຼື SRWLOCK ໃນ Windows, ຫຼືເຂົາເຈົ້າຈະໃຊ້ຫ້ອງສະໝຸດພາກສ່ວນທີສາມເຊັ່ນ Boost. ຄະນະກໍາມະການມາດຕະຖານ C++17 ໄດ້ຮັບຮູ້ຊ່ອງຫວ່າງນີ້ ແລະແນະນໍາ std::shared_mutex ໃນສ່ວນຫົວ ເພື່ອແກ້ໄຂມັນໂດຍກົງ.

ແນວຄວາມຄິດຫຼັກແມ່ນກົງໄປກົງມາ: ໃນຫຼາຍໂຄງການໃນໂລກທີ່ແທ້ຈິງ, ຂໍ້ມູນຖືກອ່ານເລື້ອຍໆຫຼາຍກວ່າທີ່ມັນຖືກຂຽນ. ມາດຕະຖານ std::mutex serializes ການເຂົ້າເຖິງທັງຫມົດ — reads include — ທີ່ສ້າງຄໍຂວດທີ່ບໍ່ຈໍາເປັນ. std::shared_mutex ຍົກຂໍ້ຈຳກັດນັ້ນໂດຍການຈຳແນກລະຫວ່າງສອງໂໝດລັອກ:

  • ແບ່ງປັນ (ອ່ານ) lock — ໄດ້ມາຜ່ານ 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 
#ລວມທັງ 

ຫ້ອງຮຽນ ConfigRegistry {
    mutable std::shared_mutex mtx_; // ປົກປ້ອງແຜນທີ່ຂ້າງລຸ່ມນີ້
    std::unordered_map data_;

ສາທາລະນະ:
    // ເສັ້ນທາງອ່ານ: ຫຼາຍຫົວຂໍ້ອາດຈະໂທຫານີ້ພ້ອມກັນ
    std::string get(const std::string&key) const {
        std::shared_lock lock(mtx_); // lock ແບ່ງປັນ — ປອດໄພສໍາລັບການອ່ານພ້ອມກັນ
        auto it = data_.find(key);
        ສົ່ງຄືນມັນ != data_.end() ? it->ວິນາທີ : "";
    }

    // ຂຽນເສັ້ນທາງ: ການເຂົ້າເຖິງສະເພາະທີ່ຕ້ອງການ
    void set(const std::string&key, const std::string&val) {
        std::unique_lock lock(mtx_); // lock exclusive — ຕັນ​ຜູ້​ອ່ານ​ທັງ​ຫມົດ​
        data_[key] = val;
    }
};

ໃຫ້ສັງເກດວິທີທີ່ຄໍາເຫັນອະທິບາຍເຖິງຄວາມຕັ້ງໃຈທີ່ຢູ່ເບື້ອງຫຼັງການເລືອກລັອກແຕ່ລະອັນ ແທນທີ່ຈະເປັນພຽງການຢ້ອນຄືນສິ່ງທີ່ລະຫັດເຮັດ. ນີ້ແມ່ນມາດຕະຖານຄຳ: ຄຳເຫັນຄວນຕອບ ເປັນຫຍັງ, ບໍ່ແມ່ນ ຫຍັງ. ຄໍາສໍາຄັນ mutable ໃນ mutex ອະນຸຍາດໃຫ້ get() ຖືກປະກາດ const ໃນຂະນະທີ່ຍັງສາມາດລັອກໄດ້, ເປັນຮູບແບບທົ່ວໄປ ແລະ idiomatic.

Key Insight: ໃຊ້ຕົວຫໍ່ລັອກ RAII ທຸກຄັ້ງ (std::shared_lock, std::unique_lock) ດ້ວຍ std::shared_mutex — ຢ່າໂທຫາ lock() ແລະ unlock() ດ້ວຍຕົນເອງ. ການ​ລັອກ​ດ້ວຍ​ຕົນ​ເອງ​ໃນ​ທີ່​ມີ​ຂໍ້​ຍົກ​ເວັ້ນ​ແມ່ນ​ເປັນ​ເສັ້ນ​ທາງ​ທີ່​ຮັບ​ປະ​ກັນ​ຕໍ່​ໄປ​ສູ່​ການ deadlocks ແລະ​ພຶດ​ຕິ​ກໍາ​ທີ່​ບໍ່​ໄດ້​ກໍາ​ນົດ.

ໄພອັນຕະລາຍທົ່ວໄປແມ່ນຫຍັງເມື່ອເຮັດວຽກກັບ std::shared_mutex?

ເຖິງແມ່ນວ່າຈະມີຄຳເຫັນທີ່ຊັດເຈນ ແລະ ເຈດຕະນາດີ, std::shared_mutex ຍັງມີກັບດັກທີ່ອ່ອນເພຍທີ່ຈະຕິດຕາມຜູ້ພັດທະນາທີ່ມີປະສົບການ. ອັນ​ຕະ​ລາຍ​ທີ່​ສຸດ​ແມ່ນ ການ​ຍົກ​ລະ​ດັບ​ການ​ລັອກ: ບໍ່​ມີ​ວິ​ທີ​ການ​ໃນ​ຕົວ​ເພື່ອ​ຍົກ​ລະ​ດັບ lock ທີ່​ແບ່ງ​ປັນ​ເປັນ​ການ​ລັອກ​ສະ​ເພາະ​ໂດຍ​ບໍ່​ມີ​ການ​ປ່ອຍ​ມັນ​ກ່ອນ​. ການພະຍາຍາມເຮັດແນວນັ້ນໂດຍບໍ່ປ່ອຍຕົວສ້າງການຕາຍຕົວທັນທີເພາະວ່າກະທູ້ຖືລັອກທີ່ໃຊ້ຮ່ວມກັນໃນຂະນະທີ່ລໍຖ້າການລັອກແບບພິເສດທີ່ບໍ່ສາມາດອະນຸຍາດໄດ້ຕາບໃດທີ່ລັອກທີ່ໃຊ້ຮ່ວມກັນທີ່ມີຢູ່ - ລວມທັງອັນທີ່ມັນຖືຢູ່.

💡 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 →

ຄວາມຜິດພາດທົ່ວໄປອີກອັນໜຶ່ງແມ່ນການປົກປ້ອງຂໍ້ມູນອັນບໍ່ຖືກຕ້ອງ. ນັກພັດທະນາບາງຄັ້ງລັອກກວ້າງເກີນໄປ, ເອົາຊະນະຈຸດປະສົງຂອງຮູບແບບຜູ້ອ່ານ, ຫຼືແຄບເກີນໄປ, ເຮັດໃຫ້ປ່ອງຢ້ຽມທີ່ invariant ຖືກລະເມີດລະຫວ່າງສອງການຊື້ lock ແຍກຕ່າງຫາກ. ຄຳເຫັນທີ່ອະທິບາຍເຖິງ ຕົວແປທີ່ຖືກປົກປ້ອງ, ແທນທີ່ຈະເປັນຕົວແປທີ່ຖືກລັອກ, ຊ່ວຍທີມງານໃຫ້ເຫດຜົນກ່ຽວກັບຄວາມຖືກຕ້ອງໃນລະຫວ່າງການກວດສອບລະຫັດ.

ການ​ປະ​ຕິ​ບັດ​ຍັງ​ສາ​ມາດ surprise ທ່ານ. ໃນລະບົບທີ່ມີການໂຕ້ຖຽງກັນສູງກັບນັກຂຽນຫຼາຍຄົນ, 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() ສໍາລັບຄວາມພະຍາຍາມຕາມເວລາ. std::shared_mutex ຂອງ C++17 ວາງຕົວແປທີ່ກຳນົດເວລາໄວ້ເພື່ອການຈັດຕັ້ງປະຕິບັດທີ່ອ່ອນກວ່າ. ຖ້າ​ຫາກ​ວ່າ​ທ່ານ​ຕ້ອງ​ການ​ການ​ລັອກ​ຕາມ​ເວ​ລາ​ໃນ​ເສັ້ນ​ທາງ​ທີ່​ແບ່ງ​ປັນ​, 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 ເພື່ອ​ອະ​ທິ​ບາຍ​ວ່າ​ຂໍ້​ມູນ​ທີ່​ມັນ​ປົກ​ປ້ອງ​ແລະ invariants ຂອງ​ມັນ​ຮັກ​ສາ​ໄວ້. ໃນແຕ່ລະສະຖານທີ່ລັອກ, ຄໍາເຫັນສັ້ນໆທີ່ອະທິບາຍວ່າເປັນຫຍັງການແບ່ງປັນກັບການເຂົ້າເຖິງແບບພິເສດໄດ້ຖືກເລືອກເພີ່ມມູນຄ່າທີ່ສໍາຄັນສໍາລັບນັກທົບທວນລະຫັດແລະຜູ້ຮັກສາໃນອະນາຄົດ. ແມງໄມ້ທີ່ກົງກັນແມ່ນເປັນອັນນຶ່ງທີ່ຍາກທີ່ສຸດໃນການແຜ່ພັນ ແລະແກ້ໄຂ, ສະນັ້ນ ການລົງທຶນໃນຄໍາຄິດເຫັນທີ່ຊັດເຈນ ແລະຊັດເຈນຈະຈ່າຍເງິນປັນຜົນຫຼາຍຄັ້ງ.


ການຄຸ້ມຄອງລະບົບທີ່ຊັບຊ້ອນ — ບໍ່ວ່າຈະເປັນລະຫັດ C++ ພ້ອມກັນ ຫຼືການດຳເນີນທຸລະກິດທັງໝົດ — ຕ້ອງການເຄື່ອງມືທີ່ຖືກຕ້ອງ ແລະໂຄງສ້າງທີ່ຊັດເຈນ. Mewayz ແມ່ນ 207 ໂມດູນທຸລະກິດ OS ທີ່ໄດ້ຮັບຄວາມໄວ້ວາງໃຈຈາກຜູ້ໃຊ້ຫຼາຍກວ່າ 138,000 ຄົນເພື່ອນໍາເອົາຄວາມຊັດເຈນດຽວກັນນັ້ນມາສູ່ການຕະຫຼາດ, CRM, e-commerce, ການວິເຄາະ, ແລະອື່ນໆ, ທັງຫມົດໃນເວທີດຽວເລີ່ມຕົ້ນພຽງແຕ່ $19 ຕໍ່ເດືອນ. ຢຸດ juggling ອາຍແກັສຂອງອຸປະກອນທີ່ຕັດການເຊື່ອມຕໍ່ແລະເລີ່ມຕົ້ນດໍາເນີນທຸລະກິດຂອງທ່ານດ້ວຍຄວາມແມ່ນຍໍາຂອງຊອບແວທີ່ອອກແບບມາດີ. ລອງໃຊ້ 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