MST

星途 面试题库

面试题:Go中如何基于channel实现简单信号量

请简述在Go语言里,怎样利用channel数据结构来模拟实现一个简单的信号量,包括初始化、获取信号量和释放信号量的具体步骤及代码实现示例。
43.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

初始化信号量

在Go语言中,可以通过创建一个带有缓冲区的channel来模拟信号量。缓冲区的大小即为信号量的初始值。

func NewSemaphore(capacity int) chan struct{} {
    return make(chan struct{}, capacity)
}

获取信号量

获取信号量意味着从channel中接收一个值。如果channel为空(没有可用信号量),接收操作会阻塞,直到有信号量被释放。

func Acquire(semaphore chan struct{}) {
    semaphore <- struct{}{}
}

释放信号量

释放信号量就是向channel中发送一个值,增加可用的信号量。

func Release(semaphore chan struct{}) {
    <-semaphore
}

完整示例代码

package main

import (
    "fmt"
    "sync"
    "time"
)

func NewSemaphore(capacity int) chan struct{} {
    return make(chan struct{}, capacity)
}

func Acquire(semaphore chan struct{}) {
    semaphore <- struct{}{}
}

func Release(semaphore chan struct{}) {
    <-semaphore
}

func worker(id int, semaphore chan struct{}, wg *sync.WaitGroup) {
    defer wg.Done()
    Acquire(semaphore)
    fmt.Printf("Worker %d acquired the semaphore\n", id)
    time.Sleep(time.Second)
    fmt.Printf("Worker %d released the semaphore\n", id)
    Release(semaphore)
}

func main() {
    semaphore := NewSemaphore(3)
    var wg sync.WaitGroup
    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go worker(i, semaphore, &wg)
    }
    wg.Wait()
}

在上述代码中:

  1. NewSemaphore 函数创建一个带有指定缓冲区大小的channel来初始化信号量。
  2. Acquire 函数尝试获取信号量,通过向channel发送一个空结构体来占用信号量。
  3. Release 函数释放信号量,通过从channel接收一个值来归还信号量。
  4. main 函数中,创建了一个容量为3的信号量,并启动5个goroutine来模拟并发操作,每个goroutine获取信号量、执行一些工作,然后释放信号量。