一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Golang - Go語言線程安全之互斥鎖與讀寫鎖

Go語言線程安全之互斥鎖與讀寫鎖

2022-02-25 23:55酷爾。 Golang

這篇文章主要介紹了Go語言線程安全之互斥鎖與讀寫鎖,互斥鎖是為了并發的安全,在多個goroutine共同工作的時候,對于共享的數據十分不安全,而讀寫鎖效率革命,使用鎖的時候,安全與效率往往需要互相轉換,下文詳細內容,需要的

前言:

單個線程時數據操作的只有一個線程,數據的修改也只有一個線程參與,數據相對來說是安全的,多線程時對數據操作的不止一個線程,所以同時對數據進行修改的時候難免紊亂

一、互斥鎖是什么?

1.概念

互斥鎖是為了并發的安全,在多個goroutine共同工作的時候,對于共享的數據十分不安全寫入時容易因為競爭造成數據不必要的丟失。互斥鎖一般加在共享數據修改的地方。

2.未加鎖

  • 線程不安全,操作的全局變量會計算異常
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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.加鎖之后

  • 線程安全,全局變量計算無異常
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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.使用方法

代碼如下(示例):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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))
}

三、sync.once

1.sync.once產生背景

 在多個goroutine中往往會由于線程不同步造成數據讀寫的沖突,特別是在進行文件打開對象創建的時候,可能會造成向關閉的文件寫內容,使用未初始化的對象,或者對一個對象進行多次初始化。

2.sync.once機制概述

sync.once保證函數內的代碼只執行一次, 實現的機制是在once內部有一個標志位,在執行代碼的時候執行一次之后標志位將置為1后續判斷標志位,如果標志位被改為1則無法再進行操縱

3.sync.once注意點

 sync.Once.Do()傳進去的函數參數無參無返,一個once對象只能執行一次Do方法,向Do方法內傳多個不同的函數時只能執行第一個傳進去的,傳進去Do方法的函數無參無返,可以用函數閉包把需要的變量傳進去

4.使用方法

  •  一般結合并發使用,旨在對通道或文件只進行一次關閉
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func f2(a <-chan int, b chan<- int) {
    for {
        x, ok := <-a
        if !ok {
            break
        }
        fmt.Println(x)
        b <- x * 10
    }
    // 確保b通道只關閉一次
    once.Do(func() {
        close(b)
    })
}

四、atomic原子包操作

原子包將指定的數據進行安全的加減交換操作; 網上還有一大堆關于原子包的api感興趣的小伙伴可以自行百度,這里就不細細闡述了

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package main
 
import (
    "fmt"
    "sync"
    "sync/atomic"
)
 
var x int64 = 0
 
var wg sync.WaitGroup
 
/*
    原子操作是將數據進行打包枷鎖,直接通過指定的函數進行相應的操作
    可以使用load讀取、store寫入、add修改、swap交換。
    // 類似于讀取一個變量、對一個變量進行賦值
*/
func addone() {
    // 沒有加鎖進行并發的話,會產生數據丟失的情況
    defer wg.Done()
    // x++
 
    // 不用加鎖也可以使用的行云流水
    // 第一個參數是進行操作的數據,第二個是增加的步長
    atomic.AddInt64(&x, 1)
 
}
func csf() {
    // 進行比較相等則將新值替換舊值
    ok := atomic.CompareAndSwapInt64(&x, 100, 200)
    fmt.Println(ok, x)
}
 
func main() {
    for i := 0; i < 50000; i++ {
        wg.Add(1)
        go addone()
    }
    wg.Wait()
    fmt.Println(x)
    x = 100
    csf()
    fmt.Println(123)
}

總結:
讀寫鎖區分讀者和寫者,而互斥鎖不區分 互斥鎖同一時間只允許一個線程訪問該對象,無論讀寫;讀寫鎖同一時間內只允許一個寫者, 但是允許多個讀者同時讀對象。 聯系:讀寫鎖在獲取寫鎖的時候機制類似于互斥鎖。

到此這篇關于Go語言線程安全之互斥鎖與讀寫鎖的文章就介紹到這了,更多相關Go語言互斥鎖與讀寫鎖內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/apple_51931783/article/details/122553203

延伸 · 閱讀

精彩推薦
  • Golanggo日志系統logrus顯示文件和行號的操作

    go日志系統logrus顯示文件和行號的操作

    這篇文章主要介紹了go日志系統logrus顯示文件和行號的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    SmallQinYan12302021-02-02
  • Golanggolang如何使用struct的tag屬性的詳細介紹

    golang如何使用struct的tag屬性的詳細介紹

    這篇文章主要介紹了golang如何使用struct的tag屬性的詳細介紹,從例子說起,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看...

    Go語言中文網11352020-05-21
  • Golanggolang的httpserver優雅重啟方法詳解

    golang的httpserver優雅重啟方法詳解

    這篇文章主要給大家介紹了關于golang的httpserver優雅重啟的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,...

    helight2992020-05-14
  • Golanggolang json.Marshal 特殊html字符被轉義的解決方法

    golang json.Marshal 特殊html字符被轉義的解決方法

    今天小編就為大家分享一篇golang json.Marshal 特殊html字符被轉義的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    李浩的life12792020-05-27
  • Golanggolang 通過ssh代理連接mysql的操作

    golang 通過ssh代理連接mysql的操作

    這篇文章主要介紹了golang 通過ssh代理連接mysql的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    a165861639710342021-03-08
  • GolangGolang通脈之數據類型詳情

    Golang通脈之數據類型詳情

    這篇文章主要介紹了Golang通脈之數據類型,在編程語言中標識符就是定義的具有某種意義的詞,比如變量名、常量名、函數名等等,Go語言中標識符允許由...

    4272021-11-24
  • GolangGolang中Bit數組的實現方式

    Golang中Bit數組的實現方式

    這篇文章主要介紹了Golang中Bit數組的實現方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    天易獨尊11682021-06-09
  • Golanggo語言制作端口掃描器

    go語言制作端口掃描器

    本文給大家分享的是使用go語言編寫的TCP端口掃描器,可以選擇IP范圍,掃描的端口,以及多線程,有需要的小伙伴可以參考下。 ...

    腳本之家3642020-04-25
主站蜘蛛池模板: 高h折磨调教古代 | 男人肌肌捅女人 | 色综色天天综合网 | 双性总裁被调教1v1 双性双根 | 亚洲国产成人精品激情 | 亚洲大逼| 被强迫变性翘秘书 | 公交车揉捏大乳呻吟喘娇 | 男女做受快插大片 | 五月婷婷在线免费观看 | 四虎影视紧急入口地址大全 | 99精品热线在线观看免费视频 | 男人搡女人视频免费看 | www亚洲国产 | 国模孕妇季玥全部人体写真 | 色哟哟在线播放 | 日韩精品亚洲一级在线观看 | 欧美x×x| 国内精品久久久久久久久久久久 | 海绵宝宝第二季全集免费观看 | 天天欲色成人综合网站 | 国产精品亚洲片夜色在线 | 欧美日韩va| 精品无人区麻豆乱码1区2 | 欧美亚洲国产精品久久久 | 高清女主播一区二区三区 | aaa免费看 | 精灵之森高清在线 | 洗濯屋し在线观看 | 日韩毛片免费 | 国产一二在线观看视频网站 | 午夜宅男在线观看 | 99久久www免费 | 欧美一级二级片 | 性欧美videosex18嫩 | 四虎影音在线 | 俄罗斯freeoo性另类 | 国产真实乱子伦xxxxchina | ai换脸杨颖啪啪免费网站 | www亚洲精品| 免费观看大片毛片 |