showliuzp 2025-10-30 20:14 采纳率: 84.3%
浏览 3
已结题

golang对结构体赋值的数据竞争


//代码1:
var (
    lock     sync.Mutex
    instance *UserInfo
)

func getInstance() (*UserInfo, error) {
    if instance == nil {
        //---Lock
        lock.Lock()
        defer lock.Unlock()
        if instance == nil {
            instance = &UserInfo{
                Name: "fan",
            }
        }
    }//---Unlock()
    return instance, nil
}

我在网上看到这个代码,说是有数据竞争,在UserInfo赋值的阶段,解决方案:

代码2:

var flag uint32

func getInstance() (*UserInfo, error) {
   if atomic.LoadUint32(&flag) != 1 {
      lock.Lock()
      defer lock.Unlock()
      if instance == nil {
         // 其他初始化错误,如果有错误可以直接返回
     instance = &UserInfo{
            Age: 18,
         }
         atomic.StoreUint32(&flag, 1)
      }
   }
   return instance, nil
}

我有几个疑问:
1、使用atomic.LoadUint32原则性检查flag值有没有变化,如果在这一步换成mutex.Lock不行么,使用LoadUint32的判断,UserInfo的赋值一定是原子的么
2、在代码1的开始出加锁,是不是可以减少刚开始的if instance == nil 的判断,变成这样:
func getInstance() (*UserInfo, error) {    
        //---Lock
        lock.Lock()
        defer lock.Unlock()    
            instance = &UserInfo{
                Name: "fan",
            }    
    return instance, nil
}
这样有何不妥?
  • 写回答

3条回答 默认 最新

  • 阿里嘎多学长 2025-10-30 20:17
    关注

    阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程

    数据竞争问题分析

    你提到的代码1存在数据竞争问题。数据竞争是指多个 goroutine 同时访问共享资源时,可能导致的竞争和冲突。

    在你的代码中,lock 是一个 sync.Mutex,用于保护 instance 的访问。但是,在 getInstance() 函数中,lock 并没有被正确地锁定和解锁。

    问题原因

    问题原因在于 lockgetInstance() 函数中没有被正确地锁定和解锁。具体来说,lock.Lock()lock.Unlock() 方法没有被正确地调用。

    解决方案

    为了解决这个问题,我们需要在 getInstance() 函数中正确地锁定和解锁 lock。具体的解决方案如下:

    func getInstance() (*UserInfo, error) {
        lock.Lock()
        defer lock.Unlock()
        // ...
    }
    

    在上面的代码中,我们使用 defer 关键字来确保 lock.Unlock() 方法在函数返回之前被调用,这样就可以确保 lock 被正确地解锁。

    最佳实践

    为了避免数据竞争问题,我们应该遵循以下最佳实践:

    • 使用 sync.Mutex 或其他同步原语来保护共享资源的访问。
    • 在函数中正确地锁定和解锁同步原语。
    • 使用 defer 关键字来确保同步原语被正确地解锁。

    通过遵循这些最佳实践,我们可以避免数据竞争问题并确保程序的正确性和安全性。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 11月7日
  • 已采纳回答 10月30日
  • 创建了问题 10月30日