MST

星途 面试题库

面试题:Go类型赋值边界控制在并发场景下的处理

在Go语言并发编程中,有一个共享变量 `type Counter int`,其值应该始终保持在0到1000之间。现在有多个goroutine会对这个 `Counter` 变量进行赋值操作,你需要设计一个方案,确保在并发环境下对 `Counter` 的赋值都在规定边界内,同时尽可能提高性能,减少锁争用。请描述你的设计思路并给出关键代码实现。
21.4万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 使用 sync.Mutex 来保护共享变量 Counter,但为了减少锁争用,采用读写分离的思路。读操作可以在无锁情况下进行,只有写操作需要加锁。
  2. 为了进一步提高性能,可以考虑使用 sync.RWMutex,读操作使用读锁,写操作使用写锁。同时,在每次写操作前,先检查要赋值的值是否在0到1000之间,避免不必要的锁操作。

关键代码实现

package main

import (
    "fmt"
    "sync"
)

type Counter int

var (
    counter Counter
    mu      sync.RWMutex
)

// Increment 增加Counter的值
func Increment(value int) {
    mu.Lock()
    defer mu.Unlock()
    if int(counter)+value >= 0 && int(counter)+value <= 1000 {
        counter += Counter(value)
    }
}

// Decrement 减少Counter的值
func Decrement(value int) {
    mu.Lock()
    defer mu.Unlock()
    if int(counter)-value >= 0 && int(counter)-value <= 1000 {
        counter -= Counter(value)
    }
}

// GetCounter 获取Counter的值
func GetCounter() Counter {
    mu.RLock()
    defer mu.RUnlock()
    return counter
}

你可以这样测试上述代码:

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            Increment(100)
        }()
    }
    wg.Wait()
    fmt.Println("Final Counter:", GetCounter())
}