成人免费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-26 08:28:35

Sync.CondGolang

2023-06-06 08:28:58

Sync.OnceGolang

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-03-30 07:52:03

Golang接口

2023-11-27 15:02:37

BytesGolang

2023-05-29 09:25:38

GolangSelect

2021-06-29 10:07:24

Javalong原子操作

2010-02-26 14:29:32

Python 工具

2023-08-31 09:28:12

Golang可導出函數

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技術棧公眾號

主站蜘蛛池模板: 在线一区| 久久精品一区二区三区四区 | 久久精品这里 | 天堂免费 | 国产丝袜一区二区三区免费视频 | 九九热精品视频 | 国户精品久久久久久久久久久不卡 | 欧美精品福利 | 欧美综合一区二区 | 丁香综合 | 久久999 | 好姑娘影视在线观看高清 | 另类一区 | 99精品国自产在线观看 | 久久国产三级 | 日韩二区 | jⅰzz亚洲| 国产小视频精品 | 网站黄色在线 | 亚洲精品成人网 | 福利在线看 | 黑人一级黄色大片 | a级片在线观看 | 韩国电影久久 | 一区二区三区在线观看视频 | 伊人久久免费 | 一区二区福利视频 | 一区二区三区四区不卡 | 中文字幕在线观看视频一区 | 久久三区 | 国产视频一区二区 | 一级a性色生活片久久毛片 一级特黄a大片 | 国产一级毛片精品完整视频版 | 国产精品成人一区二区三区 | 久久国产精品精品国产色婷婷 | 亚洲男人天堂2024 | 99精品国产一区二区青青牛奶 | 亚洲国产精品精华素 | 成人不卡视频 | 欧美一级高清片 | 国产精品久久久久一区二区 |