MST

星途 面试题库

面试题:Go语言结构体方法与并发安全

假设你有一个包含多个方法的结构体,这些方法会在并发环境下被调用。请阐述如何确保这些结构体方法在并发调用时的安全性,并给出具体的实现代码示例,包括如何使用锁机制、sync包中的相关工具等。
48.6万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

确保结构体方法在并发调用时安全性的方法

  1. 使用互斥锁(Mutex):互斥锁是一种简单有效的同步机制,它可以保证在同一时间只有一个 goroutine 能够访问共享资源。在结构体方法中,通过在访问共享资源前锁定互斥锁,访问完成后解锁互斥锁来确保线程安全。
  2. 读写锁(RWMutex):如果结构体中的数据大部分时间是被读取,只有偶尔需要写入操作,可以使用读写锁。读写锁允许多个 goroutine 同时进行读操作,但只允许一个 goroutine 进行写操作。当有写操作时,所有读操作都会被阻塞。

代码示例

  1. 使用互斥锁(Mutex)
package main

import (
    "fmt"
    "sync"
)

// Counter 结构体
type Counter struct {
    count int
    mu    sync.Mutex
}

// Increment 方法增加计数器的值
func (c *Counter) Increment() {
    c.mu.Lock()
    c.count++
    c.mu.Unlock()
}

// GetCount 方法获取计数器的值
func (c *Counter) GetCount() int {
    c.mu.Lock()
    defer c.mu.Unlock()
    return c.count
}

可以通过以下方式调用:

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

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

    wg.Wait()
    fmt.Println("Final count:", counter.GetCount())
}
  1. 使用读写锁(RWMutex)
package main

import (
    "fmt"
    "sync"
)

// Data 结构体
type Data struct {
    value int
    mu    sync.RWMutex
}

// Read 方法读取数据
func (d *Data) Read() int {
    d.mu.RLock()
    defer d.mu.RUnlock()
    return d.value
}

// Write 方法写入数据
func (d *Data) Write(newValue int) {
    d.mu.Lock()
    d.value = newValue
    d.mu.Unlock()
}

调用示例:

func main() {
    var wg sync.WaitGroup
    data := Data{}

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

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            fmt.Println("Read value:", data.Read())
        }()
    }

    wg.Wait()
}

在上述代码中,Counter 结构体通过 sync.Mutex 确保 IncrementGetCount 方法在并发调用时的安全性。Data 结构体通过 sync.RWMutex 确保读操作(Read 方法)和写操作(Write 方法)在并发环境下的安全。写操作使用 Lock 方法,读操作使用 RLock 方法。