Go Academy · บทเรียน

sync.Mutex และ sync.RWMutex

รูปแบบการล็อกและการล็อกเพื่ออ่าน-เขียน

บทเรียน 1 จาก 413 ขั้นตอน

sync.Mutex และ sync.RWMutex เป็นบทเรียน Go Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Go Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดจึงต้องใช้ mutex

เมื่อโกโรทีนหลายตัวใช้สถานะที่เปลี่ยนแปลงได้ร่วมกัน การอ่านและเขียนพร้อมกันจะทำให้เกิดสภาวะแข่งขันของข้อมูล mutex จะจัดลำดับการเข้าถึง ทำให้มีโกโรทีนเพียงตัวเดียวเข้าสู่ส่วนวิกฤติในแต่ละครั้ง

พื้นฐานของ sync.Mutex

เรียก Lock ก่อนอ่านหรือเขียนสถานะที่ใช้ร่วมกัน และเรียก Unlock หลังจากนั้น ใช้ defer เพื่อรับประกันว่าจะปลดล็อกแม้ฟังก์ชันจะเกิด panic

var mu sync.Mutex
var counter int

func inc() {
    mu.Lock()
    defer mu.Unlock()
    counter++
}

การฝัง Mutex ในโครงสร้าง

ฝัง mutex ไว้ในโครงสร้างที่ mutex ปกป้อง ตามธรรมเนียมแล้วให้ประกาศ mutex ไว้เหนือฟิลด์ที่อยู่ภายใต้การควบคุมโดยตรง

type SafeCounter struct {
    mu sync.Mutex
    v  map[string]int
}
func (c *SafeCounter) Inc(key string) {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.v[key]++
}

ห้ามคัดลอก Mutex

ห้ามคัดลอก Mutex หลังจากใช้งานครั้งแรก ให้ส่งผ่านด้วยพอยน์เตอร์หรือฝังไว้ในโครงสร้างที่ส่งผ่านด้วยพอยน์เตอร์ เครื่องมือ go vet จะตรวจจับการคัดลอกได้

sync.RWMutex

sync.RWMutex อนุญาตให้มีผู้อ่านหลายตัวทำงานพร้อมกันได้ แต่ให้มีผู้เขียนได้เพียงตัวเดียว ใช้เมื่อการอ่านมีมากและการเขียนเกิดขึ้นไม่บ่อย เพื่อเพิ่มอัตราการทำงาน

var rw sync.RWMutex
var data map[string]int

func read(k string) int {
    rw.RLock()
    defer rw.RUnlock()
    return data[k]
}
func write(k string, v int) {
    rw.Lock()
    defer rw.Unlock()
    data[k] = v
}

RLock เทียบกับ Lock

RLock รับล็อกสำหรับการอ่าน (ใช้ร่วมกันได้) ส่วน Lock รับล็อกสำหรับการเขียน (ใช้โดยเฉพาะ) ล็อกสำหรับการเขียนที่กำลังรออยู่จะบล็อกล็อกสำหรับการอ่านรายการใหม่ เพื่อป้องกันผู้เขียนอดรอการทำงาน

TryLock (Go 1.18 ขึ้นไป)

mu.TryLock() จะรับล็อกเฉพาะเมื่อขณะนั้นยังไม่มีการล็อก และคืนค่าแบบบูลีน เหมาะสำหรับกรณีที่ไม่สามารถยอมให้เกิดการบล็อกได้

if mu.TryLock() {
    defer mu.Unlock()
    // critical section
}

การหยุดชะงัก

การหยุดชะงักเกิดขึ้นเมื่อโกโรทีน A ถือล็อก 1 และรอล็อก 2 ขณะที่โกโรทีน B ถือล็อก 2 และรอล็อก 1 ควรรับล็อกตามลำดับเดียวกันเสมอ และทำให้ส่วนวิกฤตสั้นที่สุด

ระดับความละเอียดของล็อก

ล็อกแบบครอบคลุมกว้างทำความเข้าใจได้ง่ายกว่า แต่ลดการทำงานพร้อมกัน การใช้ล็อกแบบละเอียดช่วยเพิ่มอัตราการทำงาน แต่เพิ่มความซับซ้อนและความเสี่ยงต่อการหยุดชะงัก ควรเริ่มจากล็อกแบบครอบคลุมกว้าง และปรับให้เหมาะสมเมื่อ profiling แสดงว่ามีการแย่งใช้ทรัพยากร

Mutex เทียบกับช่องสัญญาณ

ใช้ mutex เมื่อต้องปกป้องสถานะที่ใช้ร่วมกันและมีทั้งผู้อ่านและผู้เขียนหลายตัว ใช้ช่องสัญญาณเมื่อต้องส่งมอบข้อมูลระหว่างโกโรทีน ช่องสัญญาณใช้สำหรับการสื่อสาร ส่วน mutex ใช้สำหรับการประสานงาน

อินเทอร์เฟซ sync.Locker

sync.Locker เป็นอินเทอร์เฟซที่มี Lock และ Unlock ทั้ง Mutex และ RWMutex นำไปใช้ได้ จึงทำให้ฟังก์ชันช่วยเหลือรับชนิดใดชนิดหนึ่งก็ได้

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

คุณควรใช้ sync.RWMutex แทน sync.Mutex เมื่อใด

สรุป: Mutex และ RWMutex

ประเด็นสำคัญ:

  • Mutex ทำให้การเข้าถึงเป็นแบบอนุกรม ควร defer Unlock เสมอ
  • ห้ามคัดลอก Mutex หลังจากใช้งานครั้งแรก
  • RWMutex: ผู้อ่านหลายราย OR ผู้เขียนหนึ่งราย
  • ควรเข้าถึงล็อกตามลำดับที่สอดคล้องกันเพื่อหลีกเลี่ยงภาวะล็อกตาย
เริ่มต้นได้ฟรี

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

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

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

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

บทเรียน “sync.Mutex และ sync.RWMutex” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “sync.Mutex และ sync.RWMutex” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Go Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “sync.Mutex และ sync.RWMutex”

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

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

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

บทเรียน “sync.Mutex และ sync.RWMutex” ใช้เวลานานแค่ไหน

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

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

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

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

  1. sync.Mutex และ sync.RWMutex
  2. sync.WaitGroup
  3. sync.Once และ sync.Map
  4. ตัวตรวจจับภาวะแข่งขันและรูปแบบที่ปลอดภัย
← กลับไปที่ Go Academy