聊聊golang中的锁

网友投稿 294 2022-08-29

聊聊golang中的锁

学习过操作系统的都知道程序有临界区这个概念,临界区就是程序片段访问临界资源的那部分代码,临界区同一时刻只能有一个线程进行访问,其他线程需要访问的话必须等待资源空闲。那么一般编程语言都会使用锁来进行临界区访问控制。

golang主要有两种锁:互斥锁和读写锁

互斥锁Mutex:

Mutex 用于提供一种加锁机制(Locking Mechanism),保证同一时刻只有一个goroutine在临界区运行。

互斥锁定义如下:

var mutex sync.Mutex;

它用于对goroutine进行加锁和解锁,Lock()之后其他goroutine便不能对其锁定的区进行操作。

看下面代码:

package mainimport ( "fmt" "time")func main() { x := 0 go func() { x = x + 1 }() time.Sleep(time.Second) fmt.Println(x)}

一般它都会打印1。

但是有没有这种可能:

并发执行过程中出现时间延误,例如我goroutine1执行完后x=1,goroutine2拿到的x并不是0,而是goroutine1已经执行好的x = 1,那么x再次自加,就会返回2。

这就是由于多个goroutine对x进行操作之后可能产生的错误,没有进行临界区访问控制。

加锁:

package mainimport ( "fmt" "sync" "time")func main() { var mutex sync.Mutex x := 0 go func() { mutex.Lock() x = x + 1 mutex.Unlock() }() time.Sleep(time.Second) fmt.Println(x)}

这样的话就是线程安全了,只有一个goroutine对x进行操作。

读写锁RWMutex:

读写锁实际是一种特殊的自旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。这种锁相对于自旋锁而言,能提高并发性,因为在多处理器系统中,它允许同时有多个读者来访问共享资源,最大可能的读者数为实际的逻辑CPU数。写者是排他性的,一个读写锁同时只能有一个写者或多个读者(与CPU数相关),但不能同时既有读者又有写者。

总的来说,就是写的时候不允许读和多个写,读的时候不允许写但是允许多个读,读和写不能同时进行。

func (*RWMutex) Lockfunc (*RWMutex) Unlockfunc (*RWMutex) RLockfunc (*RWMutex) RUnlock

Lock方法将rw锁定为写入状态,禁止其他线程读取或者写入。

Unlock方法解除rw的写入锁状态,如果m未加写入锁会导致运行时错误。

RLock方法将rw锁定为读取状态,禁止其他线程写入,但不禁止读取。

RUnlock方法解除rw的读取锁状态,如果m未加读取锁会导致运行时错误。

func read() { rwmutex.RLock() fmt.Println("read i", i) rwmutex.RUnlock()}func write() { rwmutex.Lock() rand.Seed(time.Now().Unix()) i = rand.Intn(10) fmt.Println("write i", i) rwmutex.Unlock()}func main() { go func() { write() read() time.Sleep(time.Second) write() read() }() time.Sleep(2 * time.Second)}

执行结果:

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:理解golang中关键字-chan&select
下一篇:集体哭穷!蜂花、拉夏贝尔学会了“鸿星尔克式营销”,但结局却完全不同!
相关文章

 发表评论

暂时没有评论,来抢沙发吧~