刚才对golang的锁关系进行 一番思索,想着协程获取golang 对象锁的,是按先按时间先后顺序获取的,其实不然。下面请看代码,顺带写了2种读写锁的应用。
package main
import (
"sync"
"fmt"
"time"
)
//开启10个线程 同时去竞争一个互斥锁 谁有能力谁上
var mutex *sync.Mutex;
var ch chan int
func main() {
mutex=new(sync.Mutex)
fmt.Println("start")
ch=make(chan int )
for i:=0; i<10; i++ {
go TestMutex(ch,i)
}
for i:=0; i<10; i++ {
<-ch
}
}
func TestMutex(ch chan int,index int) {
fmt.Println("to enter mutex","index=",index)
mutex.Lock();
defer mutex.Unlock()
defer fmt.Println("unLock","index=",index)
fmt.Println("in mutex","index=",index)
time.Sleep(2*time.Second)
ch<-1
运行结果如下:
start
to enter mutex index= 3
to enter mutex index= 9
in mutex index= 3
to enter mutex index= 5
to enter mutex index= 6
to enter mutex index= 7
to enter mutex index= 8
to enter mutex index= 1
to enter mutex index= 0
to enter mutex index= 4
to enter mutex index= 2
unLock index= 3
in mutex index= 9
unLock index= 9
in mutex index= 5
unLock index= 5
in mutex index= 6
unLock index= 6
in mutex index= 7
unLock index= 7
in mutex index= 8
unLock index= 8
in mutex index= 1
unLock index= 1
in mutex index= 0
unLock index= 0
in mutex index= 4
in mutex index= 2
unLock index= 4
unLock index= 2
简要分析:通过运行结果发现所有协程都开始执行,但是进入锁的协程编号变成了3,不是按12345678的顺序获取互斥锁
总结:协程获取锁先后顺序不是按时间来获取,而是竞争关系谁有能力谁上
读写锁(RWmutex)的模型一: 多个协程一起读
var RWmutex *sync.RWMutex;
var RWch chan int
func main() {
RWmutex=new(sync.RWMutex)
fmt.Println("start")
RWch=make(chan int )
for i:=0; i<10; i++ {
go TestRWMutex(i)
}
for i:=0; i<10; i++ {
<-RWch
}
}
func TestRWMutex(index int) {
fmt.Println("进入读写锁,准备读点东西","index=",index)
RWmutex.RLock();
//读取数据
fmt.Println("读点东西..","index=",index)
time.Sleep(4*time.Second)
RWmutex.RUnlock()
fmt.Println("离开读写锁..","index=",index)
RWch<-1
}
运行结果:start start 进入读写锁,准备读点东西 index= 0 进入读写锁,准备读点东西 index= 2 读点东西.. index= 2 进入读写锁,准备读点东西 index= 4 读点东西.. index= 4 进入读写锁,准备读点东西 index= 9 读点东西.. index= 9 进入读写锁,准备读点东西 index= 3 读点东西.. index= 3 进入读写锁,准备读点东西 index= 8 读点东西.. index= 8 读点东西.. index= 0 进入读写锁,准备读点东西 index= 1 读点东西.. index= 1 进入读写锁,准备读点东西 index= 7 读点东西.. index= 7 进入读写锁,准备读点东西 index= 6 读点东西.. index= 6 进入读写锁,准备读点东西 index= 5 读点东西.. index= 5 离开读写锁.. index= 4 离开读写锁.. index= 3 离开读写锁.. index= 9 离开读写锁.. index= 2 离开读写锁.. index= 7 离开读写锁.. index= 1 离开读写锁.. index= 5 离开读写锁.. index= 0 离开读写锁.. index= 6
离开读写锁.. index= 8
简要分析:读锁可连续加上。
读写锁模型 写入得时候保护,只有一个协程能写其他的协程不能写
package main
import (
"fmt"
"time"
"sync"
)
var RWWmutex *sync.RWMutex;
var RWWch chan int
// 读写模型2, 写的时候什么也做不了,
//也就是写保护
func main() {
RWWmutex=new(sync.RWMutex)
fmt.Println("start")
RWWch=make(chan int )
for i:=0; i<10; i++ {
go TestRWWMutex(RWWch,i)
}
for i:=0; i<10; i++ {
<-RWWch
}
}
func TestRWWMutex(ch chan int,index int) {
fmt.Println("进入写锁","index=",index)
RWWmutex.Lock();
//写东西..
fmt.Println("正字写东西.....","index=",index)
time.Sleep(1*time.Second)
RWWmutex.Unlock()
fmt.Println("离开写锁","index=",index)
RWWch<-1
}
运行结果:
start 进入写锁 index= 0 进入写锁 index= 1 进入写锁 index= 6 进入写锁 index= 7 进入写锁 index= 2 进入写锁 index= 3 进入写锁 index= 9 正字写东西..... index= 0 进入写锁 index= 4 进入写锁 index= 5 进入写锁 index= 8 离开写锁 index= 0 正字写东西..... index= 1 正字写东西..... index= 6 离开写锁 index= 1 正字写东西..... index= 7 离开写锁 index= 6 离开写锁 index= 7 正字写东西..... index= 2 离开写锁 index= 2 正字写东西..... index= 3 离开写锁 index= 3 正字写东西..... index= 9 离开写锁 index= 9 正字写东西..... index= 4 离开写锁 index= 4 正字写东西..... index= 5 离开写锁 index= 5 正字写东西..... index= 8
离开写锁 index= 8
不难看出 写东西的时候受到了锁的保护
模型4:读写混合进行
package main
import (
"sync"
"fmt"
"time"
)
//读写同时发生的模型
//读的时候的写 NO
//写的时候读 NO
var WR_Wmutex *sync.RWMutex;
//var WR_Rmutex *sync.RWMutex;
var WRch chan int
func main() {
WR_Wmutex=new(sync.RWMutex)
fmt.Println("start")
WRch=make(chan int )
for i:=0;i<5;i++ {
go TestRW_WMutex(i)
go TestRW_RMutex(i)
}
for i:=0;i<10 ; i++ {
<-WRch
}
}
func TestRW_WMutex(index int) {
WR_Wmutex.Lock();
//写东西..
fmt.Println("BBB 测试写,正在写东西.....","index=",index)
time.Sleep(1*time.Second)
fmt.Println("BBB 测试写,即将离开写锁","index=",index)
WR_Wmutex.Unlock()
WRch<-1
}
func TestRW_RMutex(index int) {
WR_Wmutex.RLock();
//写东西..
fmt.Println("AAA 测试读,正在读东西.....","index=",index)
time.Sleep(1*time.Second)
fmt.Println("AAA 测试读,即将离开读锁","index=",index)
WR_Wmutex.RUnlock()
WRch<-1
}
运行结果:
2018-03-12 11:21:59 BBB 测试写,正在写东西..... index= 0 2018-03-12 11:22:00 BBB 测试写,即将离开写锁 index= 0 2018-03-12 11:22:00 AAA 测试读,正在读东西..... index= 4 2018-03-12 11:22:00 AAA 测试读,正在读东西..... index= 2 2018-03-12 11:22:00 AAA 测试读,正在读东西..... index= 3 2018-03-12 11:22:00 AAA 测试读,正在读东西..... index= 0 2018-03-12 11:22:00 AAA 测试读,正在读东西..... index= 1 2018-03-12 11:22:01 AAA 测试读,即将离开读锁 index= 4 2018-03-12 11:22:01 AAA 测试读,即将离开读锁 index= 2 2018-03-12 11:22:01 AAA 测试读,即将离开读锁 index= 1 2018-03-12 11:22:01 AAA 测试读,即将离开读锁 index= 3 2018-03-12 11:22:01 AAA 测试读,即将离开读锁 index= 0 2018-03-12 11:22:01 BBB 测试写,正在写东西..... index= 1 2018-03-12 11:22:02 BBB 测试写,即将离开写锁 index= 1 2018-03-12 11:22:02 BBB 测试写,正在写东西..... index= 2 2018-03-12 11:22:03 BBB 测试写,即将离开写锁 index= 2 2018-03-12 11:22:03 BBB 测试写,正在写东西..... index= 3 2018-03-12 11:22:04 BBB 测试写,即将离开写锁 index= 3 2018-03-12 11:22:04 BBB 测试写,正在写东西..... index= 4
2018-03-12 11:22:05 BBB 测试写,即将离开写锁 index= 4
改变一下读写锁加入的顺序,先加读锁,后加写锁.
func main() {
WR_Wmutex=new(sync.RWMutex)
fmt.Println("start")
WRch=make(chan int )
for i:=0;i<5;i++ {
go TestRW_RMutex(i)
go TestRW_WMutex(i)
}
for i:=0;i<10 ; i++ {
<-WRch
}
}
运行结果:
2018-03-12 11:18:19 AAA 测试读,正在读东西..... index= 0 2018-03-12 11:18:20 AAA 测试读,即将离开读锁 index= 0 2018-03-12 11:18:20 BBB 测试写,正在写东西..... index= 4 2018-03-12 11:18:21 BBB 测试写,即将离开写锁 index= 4 2018-03-12 11:18:21 AAA 测试读,正在读东西..... index= 4 2018-03-12 11:18:21 AAA 测试读,正在读东西..... index= 1 2018-03-12 11:18:21 AAA 测试读,正在读东西..... index= 2 2018-03-12 11:18:21 AAA 测试读,正在读东西..... index= 3 2018-03-12 11:18:22 AAA 测试读,即将离开读锁 index= 3 2018-03-12 11:18:22 AAA 测试读,即将离开读锁 index= 2 2018-03-12 11:18:22 AAA 测试读,即将离开读锁 index= 4 2018-03-12 11:18:22 AAA 测试读,即将离开读锁 index= 1 2018-03-12 11:18:22 BBB 测试写,正在写东西..... index= 0 2018-03-12 11:18:23 BBB 测试写,即将离开写锁 index= 0 2018-03-12 11:18:23 BBB 测试写,正在写东西..... index= 1 2018-03-12 11:18:24 BBB 测试写,即将离开写锁 index= 1 2018-03-12 11:18:24 BBB 测试写,正在写东西..... index= 2 2018-03-12 11:18:25 BBB 测试写,即将离开写锁 index= 2 2018-03-12 11:18:25 BBB 测试写,正在写东西..... index= 3 2018-03-12 11:18:26 BBB 测试写,即将离开写锁 index= 3
运行结果分析:读的时候不能写,可以多次读;写的时候不能读,也不能写。