golang語言中sync/atomic包的學習與使用


package main;

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

//atomic包提供了底層的原子級內存操作
//類型共有六種:int32, int64, uint32, uint64, uintptr, unsafe.Pinter
//操作共五種:增減, 比較並交換, 載入, 存儲,交換

func main() {

	//增減操作
	var a int32;
	fmt.Println("a : ", a);
	//函數名以Add為前綴,加具體類型名
	//參數一,是指針類型
	//參數二,與參數一類型總是相同
	//增操作
	new_a := atomic.AddInt32(&a, 3);
	fmt.Println("new_a : ", new_a);
	//減操作
	new_a = atomic.AddInt32(&a, -2);
	fmt.Println("new_a : ", new_a);

	//CAS(Compare And Swap)比較並交換操作
	//函數名以CompareAndSwap為前綴,並具體類型名
	var b int32;
	fmt.Println("b : ", b);
	//函數會先判斷參數一指向的值與參數二是否相等,如果相等,則用參數三替換參數一的值。
	//最后返回是否替換成功
	atomic.CompareAndSwapInt32(&b, 0, 3);
	fmt.Println("b : ", b);

	//載入操作
	//當我們對某個變量進行讀取操作時,可能該變量正在被其他操作改變,或許我們讀取的是被修改了一半的數據。
	//所以我們通過Load這類函數來確保我們正確的讀取
	//函數名以Load為前綴,加具體類型名
	var c int32;
	wg := sync.WaitGroup{};
	//我們啟100個goroutine
	for i := 0; i < 100; i++ {
		wg.Add(1);
		go func() {
			defer wg.Done();
			tmp := atomic.LoadInt32(&c);
			if !atomic.CompareAndSwapInt32(&c, tmp, (tmp + 1)) {
				fmt.Println("c 修改失敗");
			}
		}();
	}
	wg.Wait();
	//c的值有可能不等於100,頻繁修改變量值情況下,CAS操作有可能不成功。
	fmt.Println("c : ", c);

	//存儲操作
	//與載入函數相對應,提供原子的存儲函數
	//函數名以Store為前綴,加具體類型名
	var d int32;
	fmt.Println("d : ", d);
	//存儲某個值時,任何CPU都不會都該值進行讀或寫操作
	//存儲操作總會成功,它不關心舊值是什么,與CAS不同
	atomic.StoreInt32(&d, 666);
	fmt.Println("d : ", d);

	//交換操作
	//直接設置新值,返回舊值,與CAS不同,它不關心舊值。
	//函數名以Swap為前綴,加具體類型名
	var e int32;
	wg2 := sync.WaitGroup{};
	//我們啟10個goroutine
	for i := 0; i < 10; i++ {
		wg2.Add(1);
		go func() {
			defer wg2.Done();
			tmp := atomic.LoadInt32(&e);
			old := atomic.SwapInt32(&e, (tmp + 1));
			fmt.Println("e old : ", old);
		}();
	}
	wg2.Wait();
	fmt.Println("e : ", e);
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM