目录


互斥锁

        在Golang中,互斥锁(Mutex)是一种基本的同步原语,用于实现对共享资源的互斥访问。互斥锁通过在代码中标记临界区来控制对共享资源的访问,从而保证同一时间只有一个 goroutine 可以访问共享资源,避免了并发访问时的数据竞争和不一致性问题。

        互斥锁的主要方法包括两个,分别是 Lock 和 Unlock。Lock 方法用于锁定共享资源,防止其他 goroutine 访问;Unlock 方法则用于解锁共享资源,允许其他 goroutine 访问。一般来说,在使用互斥锁时,需要先通过 Lock 方法锁定共享资源,访问共享资源,然后再通过 Unlock 方法解锁共享资源,让其他 goroutine 可以访问。

使用互斥锁的示例代码

package main

import (
    "fmt"
    "sync"
)

var count int
var mutex sync.Mutex

func increment() {
	mutex.Lock()
	count++
	mutex.Unlock()
	wg.Done()
}

func main() {
    for i := 0; i < 1000; i++ {
		wg.Add(1)
		go increment()
	}
	wg.Wait()
	fmt.Println("Final count:", count)
}
mutex.Lock()mutex.Unlock()

需要注意的是,在使用互斥锁时,一定要注意加锁和解锁的位置,否则可能会出现死锁的问题。

读写互斥锁

        Go语言中的读写互斥锁(RWMutex)是一种特殊类型的互斥锁,它允许多个协程同时读取某个共享资源,但在写入时必须互斥,只能有一个协程进行写操作。相比互斥锁,读写互斥锁在高并发读的场景下可以提高并发性能,但在高并发写的场景下仍然存在性能瓶颈。

        读写互斥锁有两个方法:RLock()和RUnlock()。在读取共享资源时,可以调用RLock()方法加读锁,在读取完成后,需要调用RUnlock()方法释放读锁。在写入共享资源时,需要调用Lock()方法加写锁,在写入完成后,需要调用Unlock()方法释放写锁。当有写锁或读写锁时,不能再加读锁或写锁,直到已经释放了所有锁。

读写互斥锁的示例代码

package main

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

var (
    value    int
    rwLock   sync.RWMutex
    waitTime time.Duration = 100 * time.Millisecond
)

func readValue() {
    rwLock.RLock()
    defer rwLock.RUnlock()
    time.Sleep(waitTime)
    fmt.Println("Read value:", value)
}

func writeValue(val int) {
    rwLock.Lock()
    defer rwLock.Unlock()
    time.Sleep(waitTime)
    value = val
    fmt.Println("Write value:", value)
}

func main() {
    // 读操作可以并行执行
    for i := 0; i < 5; i++ {
        go readValue()
    }
    // 写操作必须等待读操作全部结束后才能执行
    for i := 0; i < 5; i++ {
        go writeValue(i)
    }

    // 等待所有goroutine执行完毕
    time.Sleep(time.Second)
}
valuesync.RWMutexrwLockreadValueRLockvaluewriteValueLockvaluevalue
mainreadValuewriteValue

需要注意的是,在使用读写互斥锁时,必须保证写操作只有一个,否则就会出现竞争状态,导致数据不一致的问题。同时也需要注意使用锁的力度,避免锁的范围过大,导致性能下降。