C++ Academy · บทเรียน

std::mutex, lock_guard และ unique_lock

ปกป้องสถานะที่ใช้ร่วมกันด้วย mutex และตัวช่วยล็อกแบบ RAII

บทเรียน 2 จาก 414 ขั้นตอน

std::mutex, lock_guard และ unique_lock เป็นบทเรียน C++ Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C++ Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดจึงต้องใช้มิวเท็กซ์

เมื่อมีหลายเธรดเข้าถึงข้อมูลเดียวกัน เธรดเหล่านั้นจะแข่งขันกันเข้าถึงข้อมูล มิวเท็กซ์รับประกันการกีดกันร่วม โดยจะมีเธรดเพียงหนึ่งตัวเท่านั้นที่ถือ lock ได้ในแต่ละครั้ง

พื้นฐานของ std::mutex

สร้าง เรียก lock และเรียก unlock การใช้ lock ด้วยตนเองมีโอกาสเกิดข้อผิดพลาดได้ง่าย — ควรใช้ตัวช่วย RAII เสมอ

#include <mutex>
std::mutex mtx;

mtx.lock();
// critical section
mtx.unlock();

std::lock_guard: lock แบบ RAII

lock แบบ RAII ที่เรียบง่ายที่สุด จะเรียก lock ในตัวสร้างและเรียก unlock ในตัวทำลาย ทำงานได้เหมาะสมอย่างยิ่งกับส่วนวิกฤตที่ไม่โยนข้อยกเว้น

std::mutex mtx;
int counter = 0;

void increment() {
    std::lock_guard<std::mutex> lock(mtx);
    ++counter;
}

std::scoped_lock (C++17)

คล้ายกับ lock_guard แต่สามารถเรียก lock กับมิวเท็กซ์หลายตัวพร้อมกันได้โดยไม่เกิดเดดล็อก ควรเลือกใช้ในโค้ดสมัยใหม่

#include <mutex>
std::scoped_lock lock(mtx1, mtx2, mtx3);  // locks all atomically

std::unique_lock: lock ที่ยืดหยุ่น

มีความสามารถมากกว่า lock_guard:

  • สามารถเรียก unlock และเรียก lock ใหม่ระหว่างขอบเขตได้
  • สามารถย้ายได้ (โอนความเป็นเจ้าของได้)
  • ใช้ร่วมกับตัวแปรเงื่อนไขได้
std::unique_lock<std::mutex> lock(mtx);
lock.unlock();        // release temporarily
// ... do something without the lock ...
lock.lock();           // reacquire

การหลีกเลี่ยงเดดล็อก

เธรดสองตัวอาจเกิดเดดล็อกได้หากเรียก lock ตามลำดับที่แตกต่างกัน ให้เรียก lock ตามลำดับทั่วทั้งโปรแกรมที่สอดคล้องกัน หรือใช้ std::scoped_lock กับมิวเท็กซ์หลายตัว

std::lock สำหรับมิวเท็กซ์หลายตัว

ก่อน C++17 ให้ใช้ std::lock เพื่อเรียก lock กับมิวเท็กซ์หลายตัวอย่างเป็นอะตอมิก ส่วน std::scoped_lock ใน C++17 ใช้งานได้ชัดเจนกว่า

มิวเท็กซ์แบบเรียกซ้ำ

std::recursive_mutex อนุญาตให้เธรดเรียก lock กับมิวเท็กซ์ตัวเดิมได้หลายครั้ง โดยทั่วไปนี่เป็นสัญญาณว่าการออกแบบมีปัญหา — ควรปรับโครงสร้างใหม่แทน

try_lock และ timed_mutex

try_lock จะคืนค่าทันทีหากมีการถือ lock อยู่ std::timed_mutex รองรับความพยายามเรียก lock ที่จำกัดเวลา

lock สำหรับผู้อ่านและผู้เขียน

std::shared_mutex (C++17) อนุญาตให้มีผู้อ่านหลายตัวทำงานพร้อมกัน หรือมีผู้เขียนเพียงตัวเดียวที่เข้าถึงแบบผูกขาด ใช้กับงานที่อ่านข้อมูลเป็นหลัก

std::shared_mutex sm;
void read()  { std::shared_lock lk(sm);   /* read */ }
void write() { std::unique_lock lk(sm);   /* write */ }

ข้อแลกเปลี่ยนด้านความละเอียด

การใช้ lock ในระดับหยาบเกินไปจะลดการทำงานพร้อมกัน ส่วนการใช้ lock ในระดับละเอียดเกินไปจะเพิ่มค่าใช้จ่าย ควรวัดประสิทธิภาพและปรับแต่ง

ทางเลือกแบบไม่ใช้ lock

สำหรับสถานการณ์ที่มีการแย่งใช้ทรัพยากรสูง ให้พิจารณาโครงสร้างข้อมูลแบบไม่ใช้ lock (ตัวแปรอะตอมิก คิวแบบไม่ใช้ lock) การเขียนให้ถูกต้องทำได้ยากกว่ามาก — ควรใช้เฉพาะเมื่อจำเป็นและผ่านการตรวจสอบแล้ว

ตรวจสอบอย่างรวดเร็ว

ควรเลือก lock แบบ RAII ใดเมื่อต้องใช้ lock กับมิวเท็กซ์ หลายตัว พร้อมกัน

สรุปทบทวน

ใช้ std::lock_guard สำหรับส่วนวิกฤตที่เรียบง่าย ใช้ std::scoped_lock สำหรับมิวเท็กซ์หลายตัว และใช้ std::unique_lock เมื่อต้องการความยืดหยุ่น (ตัวแปรเงื่อนไข การเรียก unlock ด้วยตนเอง) ควรใช้ RAII เสมอ — อย่าเรียก lock หรือ unlock ด้วยตนเอง

เริ่มต้นได้ฟรี

เรียนรู้ C++ ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
51
บทเรียน
203

คำถามที่พบบ่อย

บทเรียน “std::mutex, lock_guard และ unique_lock” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “std::mutex, lock_guard และ unique_lock” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C++ Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “std::mutex, lock_guard และ unique_lock”

ปกป้องสถานะที่ใช้ร่วมกันด้วย mutex และตัวช่วยล็อกแบบ RAII คุณปฏิบัติ C++ Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C++ Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C++ Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “std::mutex, lock_guard และ unique_lock” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C++ Academy นี้ได้ไหม

ได้ บทเรียน C++ Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. std::thread: การรวมและการแยกเธรด
  2. std::mutex, lock_guard และ unique_lock
  3. ตัวแปรเงื่อนไขและรูปแบบผู้ปฏิบัติงาน
  4. พื้นฐาน std::async และ std::future
← กลับไปที่ C++ Academy