并发之锁住共享资源

Go 语言针对并发提供了传统的同步 goroutine 的机制,就是对共享资源加锁。如果需要顺序访问一个整型变量或者一段代码, atomic 和 sync 包的函数提供了很好的解决方案。
1、原子函数

package main

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

var (
	counter int64
	wg sync.WaitGroup
)

func main()  {
	wg.Add(2)

	go incCounter(1)
	go incCounter(2)

	wg.Wait()
	fmt.Printf("final counter:%d \n",counter)

}

func incCounter(id int)  {
	defer wg.Done()

	for i := 0; i < 2; i++ {
		// 安全地对 counter 加1
		atomic.AddInt64(&counter, 1)

		// 当前 goroutine 从线程退出,并放回队列中
		runtime.Gosched()
	}

}

atomic 包的 AddInt64 函数会同步整型值的加法,方法就是强制同一时刻只能有一个 goroutine 运行并完成加法操作。
另外,atomic 包的 LoadInt64 和 StoreInt64 这两个原子函数提供了一种安全地读和写一个整型值的方式。

package main

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

var(
	shutdown int64
	wg sync.WaitGroup
)

func main()  {
	wg.Add(2)

	go doWork("A")
	go doWork("B")

	time.Sleep(1 * time.Second)

	fmt.Println("shut down now")
	atomic.StoreInt64(&shutdown, 1)
	wg.Wait()

}

func doWork(sigin string)  {
	defer wg.Done()
	fmt.Printf("Doing work:%s \n", sigin)

	for {1
		time.Sleep(250 * time.Millisecond)
		if (atomic.LoadInt64(&shutdown) == 1){
			fmt.Printf("shuting work:%s \n", sigin)
			break
		}
	}

}



在上述代码中,如果 doWork goroutine 试图在main函数调用 StoreInt64 的同时调用 LoadInt64函数,那么原子函数会将这些调用互相同步,保证这些操作都是安全的,不会进入竞争状态。
2、互斥锁
另一种同步访问共享资源的方式是使用互斥锁。互斥锁用于在代码上创建一个临界区,保证同一时间只有一个 goroutine 可以执行这个临界区代码。

package main

import (
	"fmt"
	"runtime"
	"sync"
)

var(
	counter int
	wg sync.WaitGroup

	// mutx 用来定义一段代码临界区
	mutx sync.Mutex
)

func main()  {
	wg.Add(2)

	go incCounter(1)
	go incCounter(2)

	wg.Wait()
	fmt.Printf("final counter:%d \n", counter)
}

func incCounter(id int)  {
	defer wg.Done()

	for count :=0; count < 2; count++ {
		// 加锁
		mutx.Lock()
		{
			value := counter

			// 当前 goroutine 从线程退出,并放回到队列中
			runtime.Gosched()
			value++
			counter = value
		}
		// 释放锁
		mutx.Unlock()
	}


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值