goroutine的传统同步机制

goroutine的传统同步机制

goroutine是go的轻量级“线程",也叫协程。它有以下几个特点:

  1. 轻量级“线程”
  2. 非抢占式多任务处理,由协程主动交出控制权
  3. 编译器、解释器、虚拟机层面的多任务
  4. 多个携程可能在一个或多个线程上运行

go推荐的goroutine之间的同步机制是channel,基于CSP(Communication Sequential Process)模型,经典名:不要使用共享内存来通信,要使用通信来共享内存。

但是本篇文章并不将CSP模型,而是回到传统的同步机制:
WaitGroup
Mutex
Cond

针对其中的锁同步机制,goroutine如何实现:

package main

import (
	"fmt"
	"sync"
	"time"
)

type atomicInt struct{
	value int
	lock sync.Mutex
}

func (atomic *atomicInt) increment() {

	fmt.Println("对于AtomicInt进行+1操作!")

	func() {
		atomic.lock.Lock()
		defer atomic.lock.Unlock()
		atomic.value++
	}()
}

func (atomic *atomicInt) get() int{
	atomic.lock.Lock()
	defer atomic.lock.Unlock()
	return atomic.value
}

func main(){
	var a atomicInt
	a.increment()
	go func() {
		a.increment()
	}()
	time.Sleep(time.Millisecond)
	fmt.Println(a.get())
}

9 ~ 12行定义了一个atomicInt结构体,value是值,lock是这个共享变量的锁。
14 ~ 23行定义了这个结构体的increment递增方法。18 ~ 22行是对这段代码加了锁,并且用了defer来最后执行释放锁操作,这里的lock操作仅仅只针对这段代码。
25 ~ 29行定义了结构体的get方法,同理也是加锁了。
31 ~ 39行的main函数代表了主协程,go func()代表子协程,他们共享了atomicInt变量,并且都执行了+1操作,最后主协程输出最新值。

结果:
在这里插入图片描述
但是如果我们去掉所有的加锁操作,代码如下:

执行go run -race automic.go跟踪如下:
在这里插入图片描述警告主协程在22行有读操作,子协程在17行有写操作,二者是冲突的。
所以这种情况要加锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值