成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Golang中的同步工具原子操作詳解

開發 前端
原子操作是指一系列操作要么全部執行成功,要么全部執行失敗,不會有中間狀態。

前面幾篇文章介紹了Golang中互斥鎖、讀寫鎖、條件變量,雖然它們可以很好地協調對共享資源的訪問,但并不能保證原子操作。

原子操作

原子操作是指一系列操作要么全部執行成功,要么全部執行失敗,不會有中間狀態。

鎖無法保證原子性是因為:

  • 在鎖保護的臨界區代碼執行期間,其他協程無法訪問該代碼段,但是它們可以訪問其他資源,可能會導致原子操作失敗;
  • 鎖雖然能做到只讓一個goroutine執行臨界區代碼,不被其他goroutine打擾,不過仍然可能被系統中斷(因為goroutine都是統一被runtime調度的,runtime會頻繁切換一個goroutine的運行狀態)

可以看出原子操作的粒度更細,它對單個變量的訪問進行了原子化保證,在操作完成之前會阻塞其他并發操作。能夠保證原子性執行的只有原子操作,原子操作在執行過程中是不允許被中斷的。在計算機底層,原子性是由CPU支持的,所以絕對有效。Golang中的原子操作是基于操作系統和CPU的,具體功能由標準庫中的sync/atomic包提供。

sync/atomic

sync/atomic包提供的原子操作有Add、Load、Store、Swap和CompareAndSwap,這些函數支持的數據類型有int32、int64、uint32、uint64、uintptr和unsafe包中的Pointer,不過,沒有提供針對unsafe.Pointer的Add方法。具體方法如下:

  • AddInt32/AddInt64/AddUint32/AddUint64/AddUintptr: 原子地將指定的值加到一個地址中的值上。
  • CompareAndSwapInt32/CompareAndSwapInt64/CompareAndSwapUint32/CompareAndSwapUint64/CompareAndSwapUintptr/CompareAndSwapPointer: 原子地比較一個指定類型地址中的值,如果該值和參數old匹配,就在那個地址處存儲參數new。
  • SwapInt32/SwapInt64/SwapUint32/SwapUint64/SwapUintptr/SwapPointer: 原子地將值存儲在指定地址處,并返回此地址的舊值。
  • LoadInt32/LoadInt64/LoadUint32/LoadUint64/LoadUintptr/LoadPointer: 原子地返回指定地址中的值。
  • StoreInt32/StoreInt64/StoreUint32/StoreUint64/StoreUintptr/StorePointer: 原子地將指定值存儲到指定類型地址中。

此外,sync/atomic包還提供一個名稱為Value的類型,可以被用來存儲任意類型的值,結構如下:

type Value struct {
	v any
}

使用方法和示例

使用原子操作可以用于計算需要在多個goroutine之間共享的計數器。例如,計算在線用戶數量、任務完成情況等等。

package main

import (
	"fmt"
	"sync/atomic"
)

func main() {
	var counter int64
	done := make(chan bool)

	for i := 0; i < 100; i++ {
		go func() {
			atomic.AddInt64(&counter, 1)
			done <- true
		}()
	}

	for i := 0; i < 100; i++ {
		<-done
	}

	fmt.Println(counter)
}

首先聲明了一個int64類型的計數器變量counter,使用AddInt64原子操作對其進行遞增。通過使用AddInt64,確保了每個goroutine對其值的修改操作都能夠安全進行。

再看一個自旋鎖的示例:

package main

import (
	"fmt"
	"sync/atomic"
	"time"
)

func main() {
	sign := make(chan struct{}, 2)
	var num int32
	go func() {
		defer func() {
			sign <- struct{}{}
		}()
		for {
			// 定時增大num值
			time.Sleep(time.Millisecond * 500)
			newNum := atomic.AddInt32(&num, 2)
			fmt.Printf("num當前值為: %d\n", newNum)
			// 滿足條件后退出
			if newNum == 10 {
				break
			}
		}
	}()
	go func() {
		// 定時檢查num值,等于10則歸零
		defer func() {
			sign <- struct{}{}
		}()
		for {
			if atomic.CompareAndSwapInt32(&num, 10, 0) {
				fmt.Println("已將num歸零")
				break
			}
			time.Sleep(time.Millisecond * 500)
		}
	}()
	<-sign
	<-sign
}
責任編輯:姜華 來源: 今日頭條
相關推薦

2023-06-05 09:23:00

Golang同步工具

2023-06-06 08:28:58

Sync.OnceGolang

2023-06-26 08:28:35

Sync.CondGolang

2021-09-22 12:56:19

編程技能Golang

2023-05-19 07:51:15

ChannelGolang

2023-08-08 14:51:29

2014-01-09 09:45:41

原子飛原子

2010-05-19 10:22:07

2023-07-05 08:38:48

GolangGo語言

2023-08-03 08:48:07

Golang接口

2023-05-29 09:25:38

GolangSelect

2023-03-30 07:52:03

Golang接口

2023-11-27 15:02:37

BytesGolang

2021-06-29 10:07:24

Javalong原子操作

2023-08-31 09:28:12

Golang可導出函數

2010-02-26 14:29:32

Python 工具

2023-10-23 12:35:36

Golang追加操作

2023-10-31 09:10:39

2023-06-09 08:16:09

GolangStruct Tag

2023-08-02 09:07:27

Golangio 包
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲天堂成人在线视频 | 精品一区二区久久久久久久网站 | 日本成人三级电影 | 中文在线一区 | 中文字幕一区二区三区精彩视频 | 亚洲草草视频 | 黄色成人免费在线观看 | 精品一区av| 欧美精品欧美精品系列 | 亚洲美女网站 | 91在线精品视频 | 国产精品美女在线观看 | 伊人国产精品 | 人人澡视频 | 欧美一级在线 | 天堂一区二区三区 | 91麻豆精品国产91久久久更新资源速度超快 | 欧美视频在线一区 | 国产精品一区二区av | www精品美女久久久tv | 色综合久久久久 | 日本成人福利 | 欧美一区 | 国产精品久久久久无码av | 99中文字幕| 日韩视频一区二区在线 | 国产精品特级毛片一区二区三区 | 久久精品视频在线观看 | 日本三级网址 | 免费久草| 精品一区二区在线观看 | 国产精品久久久久一区二区三区 | 91精品国产高清一区二区三区 | 日韩一区二区在线视频 | 亚洲视频在线一区 | 在线欧美小视频 | 视频三区| 日本久久网 | 欧美日韩中文在线观看 | 视频一区二区在线观看 | 国产精品不卡视频 |