MST

星途 面试题库

面试题:Go中如何使用sync包封装简单并发逻辑

请阐述如何利用Go语言的sync包(如sync.Mutex、sync.WaitGroup等)封装一个并发安全的计数器逻辑,要求写出具体代码实现,并解释每部分代码的作用。
15.3万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "fmt"
    "sync"
)

// Counter 定义计数器结构体
type Counter struct {
    value int
    mutex sync.Mutex
}

// Increment 增加计数器的值
func (c *Counter) Increment() {
    c.mutex.Lock()
    c.value++
    c.mutex.Unlock()
}

// Decrement 减少计数器的值
func (c *Counter) Decrement() {
    c.mutex.Lock()
    c.value--
    c.mutex.Unlock()
}

// Value 获取计数器的值
func (c *Counter) Value() int {
    c.mutex.Lock()
    defer c.mutex.Unlock()
    return c.value
}

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

    // 启动10个goroutine来并发操作计数器
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            counter.Increment()
        }()
    }

    // 等待所有goroutine完成
    wg.Wait()

    // 输出计数器的值
    fmt.Println("Final counter value:", counter.Value())
}

代码解释

  1. Counter结构体
    • value 字段用于存储计数器的当前值。
    • mutex 字段是一个互斥锁,用于保护对 value 的并发访问,确保同一时间只有一个goroutine能修改或读取 value
  2. Increment方法
    • c.mutex.Lock() 用于锁定互斥锁,阻止其他goroutine同时进入该临界区。
    • c.value++ 增加计数器的值。
    • c.mutex.Unlock() 解锁互斥锁,允许其他goroutine访问临界区。
  3. Decrement方法
    • Increment 方法类似,先锁定互斥锁,减少计数器的值,然后解锁互斥锁。
  4. Value方法
    • 同样先锁定互斥锁,使用 defer 关键字确保函数结束时解锁互斥锁,返回计数器的当前值。
  5. main函数
    • 创建一个 sync.WaitGroup 实例 wg,用于等待所有goroutine完成。
    • 创建一个 Counter 实例 counter
    • 使用循环启动10个goroutine,每个goroutine调用 counter.Increment() 方法,并使用 wg.Add(1) 增加等待组的计数,在goroutine结束时调用 wg.Done() 减少计数。
    • wg.Wait() 等待所有goroutine完成。
    • 最后输出计数器的最终值。