Golang Mutex 到底是否应该使用指针?

LinkinStar · · 1519 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

前言

在写 go 的时候,你使用 Mutex 的时候使用的是指针还是说没有使用指针,还是随意来?

前两天我收到了下面这样的一个 PR,我突然就想到了这个问题,于是就有了这篇博客。

image
image

我一开始的想法

其实我一开始的想法很简单,因为我一直没有使用指针

  1. 在我的某些印象中我曾经记得,使用锁不申明为指针是一个代码规范类似的东西
  2. 大多数的(我看过的一些)源码中,没有见过将锁申明为指针的用法
  3. 但是当时我没有办法回答这个 PR,你总不能说我是一厢情愿吧...需要一个更加合理的解释

仔细分析

上网搜索一番

https://www.reddit.com/r/golang/comments/6uyf16/confusion_about_mutex_and_reference/

很多类似的问题都在问(你不用点开,只是举个例子)

问题关键

sync.Mutex 这个东西不能被 copy!(这个我之前也是知道的,毕竟都分析过源码了)

刨根问底

虽然这个锁不能被拷贝,那么就应该被申明为指针防止拷贝出现问题吗?

别慌,先写个例子测测看

package main

import (
    "fmt"
    "sync"
)

type Config1 struct {
    sync.Mutex
    Name string
}

type Config2 struct {
    *sync.Mutex
    Name string
}

func main() {
    c1 := Config1{Name: "1"}
    cc1 := c1
    fmt.Println(cc1.Name)
    cc1.Lock()
    cc1.Unlock()

    c2 := Config2{
        Mutex: &sync.Mutex{},
        Name:  "2",
    }
    cc2 := c2
    fmt.Println(cc2.Name)
    cc2.Lock()
    cc2.Unlock()
}

上面这个跑起来没问题,但是要注意的是,如果使用指针,你就必须对它初始化,否则会空指针。

看起来好像 copy 没问题啊?难道?让我 vet 看看

image

果然有问题,因为有拷贝。

但是结论我认为恰恰相反!!

我的结论

就应该不应该申明为指针

原因 1

假设你申明为了指针,go vet 就不会报错,那么其实你在使用的时候,在不知情的情况下你就会“复制”这个锁

原因 2

在什么时候会使用锁呢?一般是不是有一个单例对象要控制,这个对象或者某个操作要控制并发的时候用对吧。

那什么时候会复制对象呢?那么这个对象一定就不是个单例对不对?(注意这里是复制对象,而不是创建指针对象从而复制指针)

c2 := Config2{
   Mutex: &sync.Mutex{},
   Name:  "2",
}
cc2 := c2

这个写法就已经很古怪了,你复制了这个对象,并且用了同一把锁,那么问题来了:

  • 你的想法究竟是 cc2 锁的时候 c2 也要被锁住?=> 如果是这一种,那么就不应该将锁申明在对象内部。

  • 还是 cc2 锁的时候 c2 不要被锁住?=> 如果是这一种,既不能将锁申明为指针,也能进行拷贝,而应该重新申明一个对象,进行对象其他值的赋值操作。

结论

所以我的结论很明显,不应该申明为指针,申明指针容易在不经意间导致意外。

如果担心拷贝锁的问题,可以使用 go vet 进行分析,现在很多 go 的代码静态分析工具也都提供了这个功能的,其他的也可以。

当然这是我的个人观点,因为语法本身没有错,可能会在一些特殊情况下真的有用到这样的写法~如果我

感谢

在我疑惑自己的想法的时候感谢群里大佬的肯定和指点。

image

同时也感谢提出这个 PR 的同学,让我更加深刻的学会了这个知识点。

你们遇到问题也要刨根问底哦!不要放过任何一个小问题!


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:LinkinStar

查看原文:Golang Mutex 到底是否应该使用指针?

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1519 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传