MST

星途 面试题库

面试题:Go中如何利用信号量实现简单的线程安全计数器

请用Go语言编写一个简单的计数器程序,要求使用信号量来保障线程安全。程序需要包含增加和减少计数器值的方法,并且能够在多个并发协程中正确运行。
31.9万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "fmt"
    "sync"
)

type Counter struct {
    value int
    mutex sync.Mutex
}

func (c *Counter) Increment() {
    c.mutex.Lock()
    c.value++
    c.mutex.Unlock()
}

func (c *Counter) Decrement() {
    c.mutex.Lock()
    c.value--
    c.mutex.Unlock()
}

func (c *Counter) Value() int {
    c.mutex.Lock()
    defer c.mutex.Unlock()
    return c.value
}

func main() {
    var wg sync.WaitGroup
    counter := Counter{}

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            counter.Increment()
        }()
    }

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            counter.Decrement()
        }()
    }

    wg.Wait()
    fmt.Println("Final Counter Value:", counter.Value())
}
  1. 定义 Counter 结构体
    • 包含一个 int 类型的 value 字段用于存储计数器的值。
    • 包含一个 sync.Mutex 类型的 mutex 字段作为信号量来保障线程安全。
  2. Increment 方法
    • 使用 mutex.Lock() 锁定信号量,防止其他协程同时访问 value
    • 增加 value 的值。
    • 使用 mutex.Unlock() 解锁信号量。
  3. Decrement 方法
    • 同样先锁定信号量。
    • 减少 value 的值。
    • 解锁信号量。
  4. Value 方法
    • 锁定信号量。
    • 使用 defer 确保函数结束时解锁信号量,以返回 value 的当前值。
  5. main 函数
    • 创建一个 sync.WaitGroup 用于等待所有协程完成。
    • 创建一个 Counter 实例。
    • 启动10个协程来增加计数器的值,启动5个协程来减少计数器的值。
    • 使用 wg.Wait() 等待所有协程完成,最后打印计数器的最终值。