golang锁详解

go语言中的锁分为互斥锁、读写锁、原子锁即原子操作

互斥锁

概念

go语言中的互斥锁是由标准源码包sync中的Mutex结构体表示的,sync.Mutex只对外公开了两个指针方法Lock()和Unlock(),前者用于锁定互斥变量,后者用于互斥变量的解锁。并且由于go语言中defer语法糖的出现,使得我们不用担心加锁后会忘记解锁。
对于同一互斥变量的锁定操作和解锁操作是成对出现的,如锁定了一个已锁定的互斥变量,那么进行重复锁定操作的goroutine将被阻塞,直到互斥锁回到解锁状态,即外部的锁解锁为止。

package main

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

func main(){
	var mutex sync.Mutex
	fmt.Println("加锁main")
	mutex.Lock()
	fmt.Println("已经加锁main")
	for i:=0;i<3 ;i++  {
		go func(i int) {
			fmt.Println("加锁",i)
			mutex.Lock()
			fmt.Println("已经加锁",i)
		}(i)
	}
	time.Sleep(time.Second)
	fmt.Println("解锁main")
	mutex.Unlock()
	fmt.Println("已解锁main")
	time.Sleep(time.Second)
}
/****************************运行结果******************************************/
加锁main
已经加锁main
加锁 0
加锁 1
加锁 2
解锁main
已解锁main
已经加锁 0
/******************************************************************************/

在上述的代码中由于for循环外层已经被互斥锁锁住了,所以内部的再遇到互斥锁时会被阻塞,但随后main的互斥锁解锁时,会使得内部g1、g2、g3协程都有机会获得互斥锁,但只有一个goroutine能成功。

读写锁

概念

读写锁是针对读写操作的一种互斥锁,添加读锁会使多个写操作是互斥,多个读操作可以同时进行,读操作和写操作也是互斥的。写锁的方法与互斥锁的方法是完全一致的。


func  (*RWMutex)Lock()
func (*RWMutex)Unlock()func (*RWMutex)RLock()
func (*RWMutex)RUnlock()
package main

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

func main()  {
	var rw sync.RWMutex
	for i:=0;i<3 ;i++  {
		go func(i int) {
			fmt.Println("lock reading",i)
			rw.RLock()
			fmt.Println("locked",i)
			time.Sleep(time.Second*2)
			fmt.Println("Unlock reading")
			rw.RUnlock()
			fmt.Println("Unlocked")
		}(i)
	}
	time.Sleep(time.Millisecond*100)
	fmt.Println("lock writing")
	rw.Lock()
	fmt.Println("locked")

}
/*******************************************运行结果*****************************************************************/

lock reading 1
locked 1
lock reading 2
locked 2
lock reading 0
locked 0
lock writing
Unlock reading
Unlocked
Unlock reading
Unlocked
Unlock reading
Unlocked
locked

参考文献
《GO并发编程实战》第二版

你可能感兴趣的:(go语言)