今天给大家介绍下go语言线程安全,互斥锁是为了并发的安全,在多个goroutine共同工作的时候,对于共享的数据十分不安全,而读写锁效率革命,使用锁的时候,安全与效率往往需要互相转换,具体如下:
单个线程时数据操作的只有一个线程,数据的修改也只有一个线程参与,数据相对来说是安全的,多线程时对数据操作的不止一个线程,所以同时对数据进行修改的时候难免紊乱
一、互斥锁是什么?
1.概念
互斥锁是为了并发的安全,在多个goroutine共同工作的时候,对于共享的数据十分不安全写入时容易因为竞争造成数据不必要的丢失。互斥锁一般加在共享数据修改的地方。
2.未加锁
线程不安全,操作的全局变量会计算异常
package main
import (
"fmt"
"sync"
)
var x int = 0
var wg sync.WaitGroup
func add() {
defer wg.Done()
for i := 0; i < 5000; i++ {
x++
}
}
func main() {
wg.Add(2)
go add()
go add()
wg.Wait()
fmt.Println(x)
}
/*
打印结果:(每次打印不一样,正常的结果应该是10000)
6051
5059
5748
10000
*/
3.加锁之后
线程安全,全局变量计算无异常
package main
import (
"fmt"
"sync"
)
var x int = 0
var wg sync.WaitGroup
// 创建一个锁对象
var lock sync.Mutex
func add() {
defer wg.Done()
for i := 0; i < 5000; i++ {
//加锁
lock.Lock()
x++
//解锁
lock.Unlock()
}
}
func main() {
wg.Add(2)
//开启两个线程
go add()
go add()
wg.Wait()
fmt.Println(x)
}
/*
打印结果:
全为10000
*/
二、读写锁【效率革命】
1.为什么读写锁效率高
使用锁的时候,安全与效率往往需要互相转换,对数据进行操作的时候,只会进行数据的读与写。 而读与读之间可以同时进行,读与写之间需要保证写的时候不去读。此时为了提高效率就发明读写锁,在读写锁机制下,安全没有丝毫降低,但效率进行了成倍的提升提升的效率在读与写操作次数差异越大时越明显
2.使用方法
代码如下(示例):
package main
import (
"fmt"
"sync"
"time"
)
var (
x = 0
rwlock sync.RWMutex
wg sync.WaitGroup
)
func write() {
defer wg.Done()
rwlock.Lock()
x++
rwlock.Unlock()
}
func read() {
wg.Done()
//开启读锁
rwlock.RLock()
fmt.Println(x)
//释放读锁
rwlock.RUnlock()
}
func main() {
start := time.Now()
for i := 0; i < 100; i++ {
wg.Add(1)
go write()
}
// time.Sleep(time.Second)
for i := 0; i < 10000; i++ {
wg.Add(1)
go read()
}
wg.Wait()
fmt.Println(time.Now().Sub(start))
}
以上便是go语言线程安全,常用方法的全部内容,更多内容干货可关注慕课网~