最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go互斥鎖和讀寫鎖完整代碼舉例

 更新時(shí)間:2026年06月03日 10:35:22   作者:QX_hao  
讀寫鎖(sync.RWMutex)與互斥鎖(sync.Mutex)是Go語言中兩種最核心的并發(fā)控制機(jī)制,本質(zhì)區(qū)別在于對(duì)讀操作的并發(fā)支持,這篇文章主要介紹了Go互斥鎖和讀寫鎖的相關(guān)資料,需要的朋友可以參考下

作用

互斥鎖(Mutex)和讀寫鎖(RWMutex)是Go語言中用于保護(hù)共享資源、防止數(shù)據(jù)競(jìng)爭(zhēng)的重要同步機(jī)制。

1. 數(shù)據(jù)競(jìng)爭(zhēng)問題

1.1 數(shù)據(jù)競(jìng)爭(zhēng)

數(shù)據(jù)競(jìng)爭(zhēng)(Data Race)發(fā)生在多個(gè)goroutine并發(fā)訪問同一共享變量,且至少有一個(gè)訪問是寫入操作時(shí)。如果沒有適當(dāng)?shù)耐綑C(jī)制,會(huì)導(dǎo)致不可預(yù)測(cè)的結(jié)果。

1.2 數(shù)據(jù)競(jìng)爭(zhēng)的危害

  • 結(jié)果不確定性:相同的代碼可能產(chǎn)生不同的結(jié)果
  • 內(nèi)存損壞:可能導(dǎo)致程序崩潰或數(shù)據(jù)損壞
  • 難以調(diào)試:?jiǎn)栴}可能只在特定條件下出現(xiàn)

2. 互斥鎖(Mutex)

2.1 互斥鎖

互斥鎖(Mutual Exclusion Lock)是最基本的同步原語,保證同一時(shí)間只有一個(gè)goroutine可以訪問受保護(hù)的臨界區(qū)。

2.2 互斥鎖操作

var mutex sync.Mutex

// 加鎖
mutex.Lock()

// 臨界區(qū)代碼
// ...

// 解鎖
mutex.Unlock()

3. 代碼示例分析

3.1 數(shù)據(jù)競(jìng)爭(zhēng)演示

package test_lock

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

var wait sync.WaitGroup
var count1 = 0

func Demo01() {
	wait.Add(10)
	for i := 0; i < 10; i++ {
		go func(data *int) {
			// 模擬訪問耗時(shí)
			time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000)))
			// 訪問數(shù)據(jù)
			temp := *data
			// 模擬計(jì)算耗時(shí)
			// 拉大時(shí)間,讓數(shù)據(jù)競(jìng)爭(zhēng)更嚴(yán)重(更好觀察結(jié)果)
			time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000)))
			ans := 1
			// 修改數(shù)據(jù)
			*data = temp + ans
			fmt.Println("goroutine", i, "count1:", *data)
			wait.Done()
		}(&count1)
	}
	wait.Wait()
	fmt.Println("最終結(jié)果", count1)
}

核心要點(diǎn):

  1. 無鎖并發(fā)訪問

    var count1 = 0
    
    go func(data *int) {
        temp := *data           // 讀取共享變量
        // ... 計(jì)算耗時(shí)
        *data = temp + ans      // 寫入共享變量
    }(&count1)
    
  2. 數(shù)據(jù)競(jìng)爭(zhēng)特征

    • 多個(gè)goroutine同時(shí)讀寫count1變量
    • 讀-改-寫操作不是原子的
    • 最終結(jié)果通常小于預(yù)期值

關(guān)鍵:

  • 典型的數(shù)據(jù)競(jìng)爭(zhēng)
  • 由于goroutine執(zhí)行順序不確定,結(jié)果不可預(yù)測(cè)
  • 需要同步機(jī)制來保證正確性

3.2 互斥鎖解決方案

package test_lock

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

var wg sync.WaitGroup
var count = 0

// 聲明一個(gè)互斥鎖
var mutex sync.Mutex

func Demo02() {
	wg.Add(10)
	for i := 0; i < 10; i++ {
		go func(data *int) {
			// 加鎖
			mutex.Lock()

			// 模擬訪問耗時(shí)
			time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000)))
			// 訪問數(shù)據(jù)
			temp := *data
			// 模擬計(jì)算耗時(shí)
			// 拉大時(shí)間,讓數(shù)據(jù)競(jìng)爭(zhēng)更嚴(yán)重(更好觀察結(jié)果)
			time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000)))
			ans := 1
			// 修改數(shù)據(jù)
			*data = temp + ans

			// 解鎖
			mutex.Unlock()

			fmt.Println("goroutine", i, "count:", *data)
			wg.Done()
		}(&count)
	}
	wg.Wait()
	fmt.Println("最終結(jié)果", count)
}

核心要點(diǎn):

  1. 互斥鎖保護(hù)臨界區(qū)

    var mutex sync.Mutex
    
    go func(data *int) {
        // 加鎖
        mutex.Lock()
        
        temp := *data
        // ... 計(jì)算耗時(shí)
        *data = temp + ans
        
        // 解鎖
        mutex.Unlock()
    }(&count)
    
  2. 鎖的正確使用

    • 在訪問共享資源前加鎖
    • 在操作完成后立即解鎖
    • 使用defer確保解鎖被執(zhí)行

關(guān)鍵:

  • 互斥鎖保證了操作的原子性
  • 最終結(jié)果總是正確的(10個(gè)goroutine,每個(gè)+1,結(jié)果應(yīng)為10)
  • 性能會(huì)有一定損耗,但保證了正確性

3.3 讀寫鎖(RWMutex)

package test_lock

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

var wg3 sync.WaitGroup
var rw sync.RWMutex

// 實(shí)現(xiàn)可以多人讀  但是只能一人寫
func write(count int) {
	defer wg3.Done()
	rw.Lock()
	defer rw.Unlock()
	fmt.Println("goroutine", count, "寫操作>>>>>>>")
	time.Sleep(time.Second * 2)
}

func read(count int) {
	defer wg3.Done()
	fmt.Println("goroutine", count, "<<<<<<<<<讀操作")
	time.Sleep(time.Second * 2)
}

func Demo03() {
	for i := 0; i < 10; i++ {
		wg3.Add(1)
		go write(i)
	}

	for i := 0; i < 10; i++ {
		wg3.Add(1)
		go read(i)
	}

	wg3.Wait()
}

核心要點(diǎn):

  1. 讀寫鎖操作

    var rw sync.RWMutex
    
    // 寫鎖操作
    func write(count int) {
        rw.Lock()           // 加寫鎖
        defer rw.Unlock()   // 解讀鎖
        // 寫操作...
    }
    
    // 讀鎖操作  
    func read(count int) {
        rw.RLock()          // 加讀鎖
        defer rw.RUnlock()  // 解讀鎖
        // 讀操作...
    }
    
  2. 讀寫鎖特性

    • 讀鎖:多個(gè)goroutine可以同時(shí)持有讀鎖
    • 寫鎖:寫鎖是排他的,持有寫鎖時(shí)不能有讀鎖或其他寫鎖
    • 升級(jí)規(guī)則:讀鎖不能升級(jí)為寫鎖

關(guān)鍵:

  • 讀寫鎖適用于"讀多寫少"的場(chǎng)景
  • 提高了并發(fā)讀取的性能
  • 寫操作仍然需要獨(dú)占訪問

4. 鎖的類型對(duì)比

4.1 互斥鎖 vs 讀寫鎖

特性互斥鎖(Mutex)讀寫鎖(RWMutex)
并發(fā)讀取不支持支持多個(gè)goroutine同時(shí)讀取
寫入操作完全互斥完全互斥
性能開銷較低較高(需要維護(hù)讀鎖計(jì)數(shù))
適用場(chǎng)景讀寫頻率相當(dāng)讀多寫少

4.2 選擇原則

使用互斥鎖的情況:

  • 讀寫操作頻率相當(dāng)
  • 臨界區(qū)代碼執(zhí)行時(shí)間短
  • 代碼邏輯簡(jiǎn)單

使用讀寫鎖的情況:

  • 讀操作遠(yuǎn)多于寫操作
  • 讀操作耗時(shí)較長
  • 需要最大化讀取并發(fā)性

5. 鎖的使用場(chǎng)景

5.1 共享數(shù)據(jù)保護(hù)

// 保護(hù)共享map
var dataMap = make(map[string]string)
var mapMutex sync.RWMutex

func GetValue(key string) string {
    mapMutex.RLock()
    defer mapMutex.RUnlock()
    return dataMap[key]
}

func SetValue(key, value string) {
    mapMutex.Lock()
    defer mapMutex.Unlock()
    dataMap[key] = value
}

5.2 計(jì)數(shù)器保護(hù)

// 原子計(jì)數(shù)器
var counter int
var counterMutex sync.Mutex

func Increment() {
    counterMutex.Lock()
    defer counterMutex.Unlock()
    counter++
}

func GetCount() int {
    counterMutex.Lock()
    defer counterMutex.Unlock()
    return counter
}

5.3 資源池管理

// 連接池管理
type ConnectionPool struct {
    pool []*Connection
    mutex sync.Mutex
}

func (p *ConnectionPool) Get() *Connection {
    p.mutex.Lock()
    defer p.mutex.Unlock()
    
    if len(p.pool) > 0 {
        conn := p.pool[0]
        p.pool = p.pool[1:]
        return conn
    }
    return nil
}

6. 指南

6.1 鎖的使用

  1. 保持鎖的粒度適中

    // 錯(cuò)誤:鎖的粒度過大
    mutex.Lock()
    // 大量非臨界區(qū)代碼...
    // 共享資源訪問
    mutex.Unlock()
    
    // 正確:只保護(hù)必要的臨界區(qū)
    // 非臨界區(qū)代碼...
    mutex.Lock()
    // 共享資源訪問
    mutex.Unlock()
    // 非臨界區(qū)代碼...
    
  2. 使用defer確保解鎖

    func safeOperation() {
        mutex.Lock()
        defer mutex.Unlock()  // 確保在任何情況下都會(huì)解鎖
        
        // 可能panic的代碼
        if err != nil {
            panic("error")
        }
    }
    

6.2 避免死鎖

  1. 鎖的順序一致性

    // 錯(cuò)誤:可能產(chǎn)生死鎖
    func operation1() {
        mutexA.Lock()
        mutexB.Lock()
        // ...
        mutexB.Unlock()
        mutexA.Unlock()
    }
    
    func operation2() {
        mutexB.Lock()  
        mutexA.Lock()  // 可能死鎖
        // ...
    }
    
    // 正確:保持一致的鎖順序
    func operation1() {
        mutexA.Lock()
        mutexB.Lock()
        // ...
    }
    
    func operation2() {
        mutexA.Lock()  // 先獲取A鎖
        mutexB.Lock()  // 再獲取B鎖
        // ...
    }
    
  2. 使用超時(shí)機(jī)制

    // 使用context實(shí)現(xiàn)超時(shí)
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    
    select {
    case <-acquireLock(ctx, mutex):
        // 成功獲取鎖
    case <-ctx.Done():
        // 超時(shí)處理
    }
    

6.3 性能優(yōu)化

  1. 減少鎖競(jìng)爭(zhēng)

    • 使用更細(xì)粒度的鎖
    • 考慮使用無鎖數(shù)據(jù)結(jié)構(gòu)
    • 使用本地緩存減少鎖的使用頻率
  2. 讀寫分離

    // 使用讀寫鎖優(yōu)化讀多寫少的場(chǎng)景
    var rw sync.RWMutex
    var data []string
    
    // 多個(gè)goroutine可以同時(shí)讀取
    func ReadData() []string {
        rw.RLock()
        defer rw.RUnlock()
        return data
    }
    
    // 寫操作仍然需要互斥
    func WriteData(newData []string) {
        rw.Lock()
        defer rw.Unlock()
        data = newData
    }
    

7. 高級(jí)主題

7.1 條件變量(Cond)

條件變量用于在特定條件下等待或通知goroutine:

var mutex sync.Mutex
cond := sync.NewCond(&mutex)

// 等待條件
func waitForCondition() {
    mutex.Lock()
    for !condition {
        cond.Wait()  // 釋放鎖并等待
    }
    // 條件滿足,執(zhí)行操作
    mutex.Unlock()
}

// 通知條件滿足
func signalCondition() {
    mutex.Lock()
    condition = true
    cond.Signal()  // 通知一個(gè)等待的goroutine
    mutex.Unlock()
}

7.2 原子操作

對(duì)于簡(jiǎn)單的計(jì)數(shù)器操作,可以使用原子操作避免鎖的開銷:

import "sync/atomic"

var counter int64

func Increment() {
    atomic.AddInt64(&counter, 1)
}

func GetCount() int64 {
    return atomic.LoadInt64(&counter)
}

8. 調(diào)試和測(cè)試

8.1 數(shù)據(jù)競(jìng)爭(zhēng)檢測(cè)

使用Go內(nèi)置的競(jìng)爭(zhēng)檢測(cè)器:

# 編譯時(shí)啟用競(jìng)爭(zhēng)檢測(cè)
go build -race main.go

# 運(yùn)行程序
go run -race main.go

8.2 性能分析

使用pprof分析鎖競(jìng)爭(zhēng):

import _ "net/http/pprof"

// 在程序中啟動(dòng)pprof服務(wù)器
go func() {
    log.Println(http.ListenAndServe("localhost:6060", nil))
}()

總結(jié) 

到此這篇關(guān)于Go互斥鎖和讀寫鎖的文章就介紹到這了,更多相關(guān)Go互斥鎖和讀寫鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • GoLang之標(biāo)準(zhǔn)庫encoding/json包

    GoLang之標(biāo)準(zhǔn)庫encoding/json包

    本文主要介紹了GoLang之標(biāo)準(zhǔn)庫encoding/json包,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • Go+Kafka實(shí)現(xiàn)延遲消息的實(shí)現(xiàn)示例

    Go+Kafka實(shí)現(xiàn)延遲消息的實(shí)現(xiàn)示例

    本文主要介紹了Go+Kafka實(shí)現(xiàn)延遲消息的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Golang實(shí)現(xiàn)快速求冪的方法詳解

    Golang實(shí)現(xiàn)快速求冪的方法詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用Golang實(shí)現(xiàn)快速求冪,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定參考價(jià)值,需要的可以參考一下
    2022-06-06
  • 深入理解GoLang并發(fā)與并行

    深入理解GoLang并發(fā)與并行

    本文主要介紹了GoLang并發(fā)與并行,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-03-03
  • 使用Go語言簡(jiǎn)單模擬Python的生成器

    使用Go語言簡(jiǎn)單模擬Python的生成器

    這篇文章主要介紹了使用Go語言簡(jiǎn)單模擬Python的生成器,Python的generator是非??岬墓δ?用Go實(shí)現(xiàn)的代碼也較為簡(jiǎn)潔,需要的朋友可以參考下
    2015-08-08
  • golang?Gorm框架講解

    golang?Gorm框架講解

    gorm是一個(gè)使用Go語言編寫的ORM框架,這篇文章主要介紹了golang?Gorm框架,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • go mod私有倉庫配置小結(jié)

    go mod私有倉庫配置小結(jié)

    Go語言私有倉庫通常指的是那些不在公共倉庫如GitHub上的倉庫,本文主要介紹了go mod私有倉庫配置,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-03-03
  • Go應(yīng)用中優(yōu)雅處理Error的技巧總結(jié)

    Go應(yīng)用中優(yōu)雅處理Error的技巧總結(jié)

    在程序員中,尤其是go新手,經(jīng)常聽到的一個(gè)討論話題是:如何處理錯(cuò)誤,這篇文章主要給大家介紹了關(guān)于Go應(yīng)用中優(yōu)雅處理Error的一些相關(guān)技巧,需要的朋友可以參考下
    2021-09-09
  • 一文帶你讀懂Golang?sync包之sync.Mutex

    一文帶你讀懂Golang?sync包之sync.Mutex

    sync.Mutex可以說是sync包的核心了,?sync.RWMutex,?sync.WaitGroup...都依賴于他,?本章我們將帶你一文讀懂sync.Mutex,快跟隨小編一起學(xué)習(xí)一下吧
    2023-04-04
  • 詳解Go多協(xié)程并發(fā)環(huán)境下的錯(cuò)誤處理

    詳解Go多協(xié)程并發(fā)環(huán)境下的錯(cuò)誤處理

    這篇文章主要介紹了詳解Go多協(xié)程并發(fā)環(huán)境下的錯(cuò)誤處理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08

最新評(píng)論

武夷山市| 庆阳市| 临高县| 买车| 阳泉市| 锦屏县| 渝中区| 莱州市| 乌海市| 瓮安县| 阿城市| 大埔县| 庆阳市| 石渠县| 南宫市| 泰和县| 永川市| 大化| 浦东新区| 平果县| 犍为县| 泾阳县| 华阴市| 顺昌县| 崇义县| 安陆市| 高要市| 临沂市| 塔河县| 辉南县| 元江| 泸州市| 肇东市| 安国市| 天津市| 金堂县| 莫力| 米易县| 天镇县| 永善县| 界首市|