0Pricing
Go Academy · บทเรียน

รูปแบบเซมาฟอร์

จำกัดการทำงานพร้อมกันด้วยเซมาฟอร์ที่ใช้แชนเนล

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

เซมาฟอร์คืออะไร

เซมาฟอร์จำกัดจำนวนโกโรทีนที่ทำงานหนึ่งอย่างพร้อมกัน ช่วยป้องกันการใช้ทรัพยากรจนหมด (เช่น การเปิดการเชื่อมต่อฐานข้อมูลมากเกินไปหรือการส่งคำขอ HTTP ออกไปมากเกินไป)

ช่องสัญญาณแบบมีบัฟเฟอร์เป็นเซมาฟอร์

ช่องสัญญาณแบบมีบัฟเฟอร์ที่มีความจุ N จะทำหน้าที่เป็นเซมาฟอร์แบบนับจำนวน การขอสิทธิ์จะส่งค่าไปยังช่องสัญญาณ (และบล็อกเมื่อเต็ม) ส่วนการคืนสิทธิ์จะรับค่าจากช่องสัญญาณ

sem := make(chan struct{}, 10)

func withSem(f func()) {
    sem <- struct{}{} // acquire
    defer func() { <-sem }() // release
    f()
}

หนึ่งโกโรทีนต่องานโดยใช้เซมาฟอร์

สร้างโกโรทีนหนึ่งตัวต่องาน แต่จำกัดการทำงานพร้อมกันด้วยเซมาฟอร์:

sem := make(chan struct{}, 5)
for _, job := range jobs {
    sem <- struct{}{}
    go func(j Job) {
        defer func() { <-sem }()
        process(j)
    }(job)
}

ระบายเซมาฟอร์เมื่อสิ้นสุด

หลังจากเริ่มโกโรทีนทั้งหมดแล้ว ให้อ่านค่าจากเซมาฟอร์จนหมด เพื่อให้แน่ใจว่าทั้งหมดทำงานเสร็จก่อนส่งคืน:

// After the loop, acquire all N slots (blocks until all goroutines release)
for i := 0; i < cap(sem); i++ {
    sem <- struct{}{}
}

golang.org/x/sync/semaphore

สำหรับเซมาฟอร์แบบถ่วงน้ำหนัก (เช่น โกโรทีนที่ใช้ทรัพยากรในน้ำหนักแตกต่างกัน) ให้ใช้ชนิด semaphore.Weighted:

s := semaphore.NewWeighted(100)
// acquire 10 units
if err := s.Acquire(ctx, 10); err != nil { return err }
defer s.Release(10)
// do work

การขอสิทธิ์ตามบริบท

เมธอด Acquire ของเซมาฟอร์แบบถ่วงน้ำหนักจะเคารพบริบท และส่งคืนข้อผิดพลาดหากบริบทถูกยกเลิกก่อนที่เซมาฟอร์จะพร้อมใช้งาน

TryAcquire

s.TryAcquire(n) จะขอหน่วยจำนวน n ก็ต่อเมื่อหน่วยเหล่านั้นพร้อมใช้งานทันที หากไม่เช่นนั้นจะส่งคืน false เหมาะสำหรับการตรวจสอบแบบไม่บล็อก

เซมาฟอร์กับกลุ่มผู้ทำงาน

กลุ่มผู้ทำงานมีโกโรทีนถาวรจำนวนคงที่ ส่วนเซมาฟอร์ทำให้คุณสร้างโกโรทีนตามต้องการได้ แต่ยังจำกัดการทำงานพร้อมกัน ใช้เซมาฟอร์เมื่ออัตราการเข้ามาของงานเปลี่ยนแปลงมาก

การจำกัดการทำงานพร้อมกันของ HTTP

ห่อตัวจัดการหรือไคลเอนต์ HTTP ด้วยเซมาฟอร์ เพื่อป้องกันคำขอขาออกที่ทำงานพร้อมกันหรือโกโรทีนของตัวจัดการขาเข้ามีจำนวนมากเกินไป

การจำกัดการเชื่อมต่อฐานข้อมูล

แทนที่จะใช้เซมาฟอร์ ให้กำหนด db.SetMaxOpenConns(n) และ db.SetMaxIdleConns(m) — แพ็กเกจ sql จะจัดการการทำงานพร้อมกันของกลุ่มการเชื่อมต่อภายในให้เอง

ความเป็นธรรมของเซมาฟอร์

เซมาฟอร์ที่ใช้ช่องสัญญาณแบบมีบัฟเฟอร์มีความเป็นธรรมโดยประมาณ (เป็น FIFO สำหรับโกโรทีนที่บล็อกขณะส่ง) แต่ไม่ได้รับประกันอย่างเคร่งครัด แพ็กเกจเซมาฟอร์แบบถ่วงน้ำหนักให้การรับประกันความเป็นธรรมที่เข้มงวดกว่า

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

ช่องสัญญาณแบบมีบัฟเฟอร์นำมาใช้เป็นเซมาฟอร์ได้อย่างไร

สรุป: รูปแบบเซมาฟอร์

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

  • ใช้ช่องสัญญาณแบบมีบัฟเฟอร์ sem := make(chan struct{}, N) สำหรับเซมาฟอร์แบบง่าย
  • ส่งค่าเพื่อขอสิทธิ์ รับค่าเพื่อคืนสิทธิ์ และใช้ defer เพื่อคืนสิทธิ์เสมอ
  • ใช้ golang.org/x/sync/semaphore สำหรับรูปแบบที่กำหนดน้ำหนักและรองรับบริบท
  • ใช้ errgroup.SetLimit เพื่อจำกัดการทำงานพร้อมกันอย่างง่ายต่อกลุ่ม

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

บทเรียน “รูปแบบเซมาฟอร์” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “รูปแบบเซมาฟอร์”

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

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

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

บทเรียน “รูปแบบเซมาฟอร์” ใช้เวลานานแค่ไหน

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

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

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

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

  1. รูปแบบไปป์ไลน์และขั้นตอน
  2. errgroup สำหรับจัดการข้อผิดพลาดพร้อมกัน
  3. รูปแบบเซมาฟอร์
  4. การตรวจจับการรั่วไหลและการยกเลิก
← กลับไปที่ Go Academy