MST

星途 面试题库

面试题:Go语言中原子操作如何保证数据一致性

在Go语言中,简述原子操作是如何确保多线程环境下数据一致性的,举例说明`atomic`包中常用的原子操作函数及其适用场景。
23.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

原子操作确保多线程环境下数据一致性的原理

在Go语言中,原子操作是由底层硬件和操作系统支持的不可分割的操作。在多线程环境下,多个线程可能同时访问和修改共享数据,这会导致数据竞争和不一致问题。原子操作通过保证操作的原子性,即操作在执行过程中不会被其他线程中断,从而确保数据一致性。

atomic包中常用的原子操作函数及其适用场景

  1. atomic.AddInt64
    • 函数签名func AddInt64(addr *int64, delta int64) (new int64)
    • 适用场景:用于在多线程环境下安全地对int64类型的共享变量进行加法操作。例如,在实现计数器时,如果多个线程可能同时对计数器进行增加操作,使用atomic.AddInt64可以避免数据竞争。
    • 示例代码
package main

import (
    "fmt"
    "sync"
    "sync/atomic"
)

func main() {
    var counter int64
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            atomic.AddInt64(&counter, 1)
        }()
    }
    wg.Wait()
    fmt.Println("Final counter value:", atomic.LoadInt64(&counter))
}
  1. atomic.CompareAndSwapInt64
    • 函数签名func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)
    • 适用场景:用于实现乐观锁。只有当共享变量addr的值等于old时,才将其值更新为new,并返回true,否则返回false。常用于多线程环境下需要根据某个条件更新共享变量的场景。
    • 示例代码
package main

import (
    "fmt"
    "sync"
    "sync/atomic"
)

func main() {
    var value int64 = 10
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            success := atomic.CompareAndSwapInt64(&value, 10, 20)
            if success {
                fmt.Println("Value successfully updated")
            } else {
                fmt.Println("Value was not updated")
            }
        }()
    }
    wg.Wait()
}
  1. atomic.LoadInt64
    • 函数签名func LoadInt64(addr *int64) (val int64)
    • 适用场景:用于在多线程环境下安全地读取int64类型的共享变量。确保读取操作不会受到其他线程写操作的干扰。
    • 示例代码
package main

import (
    "fmt"
    "sync"
    "sync/atomic"
)

func main() {
    var data int64 = 42
    var wg sync.WaitGroup
    for i := 0; i < 3; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            value := atomic.LoadInt64(&data)
            fmt.Println("Read value:", value)
        }()
    }
    wg.Wait()
}
  1. atomic.StoreInt64
    • 函数签名func StoreInt64(addr *int64, val int64)
    • 适用场景:用于在多线程环境下安全地存储int64类型的值到共享变量。确保存储操作不会被其他线程干扰。
    • 示例代码
package main

import (
    "fmt"
    "sync"
    "sync/atomic"
)

func main() {
    var data int64
    var wg sync.WaitGroup
    for i := 0; i < 3; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            atomic.StoreInt64(&data, int64(i*10))
        }()
    }
    wg.Wait()
    fmt.Println("Final stored value:", atomic.LoadInt64(&data))
}