日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Go開發(fā)競態(tài)檢測科普文

一、名詞解析

1、data race: Any race is a bug

定義: ①多個線程(協(xié)程)對于同一個變量、②同時地、③進行讀/寫操作、并且④至少有一個線程進行寫操作。(也就是說,如果所有線程都是只進行讀操作,那么將不構(gòu)成數(shù)據(jù)爭用)

創(chuàng)新互聯(lián)公司2013年成立,先為沿灘等服務建站,沿灘等地企業(yè),進行企業(yè)商務咨詢服務。為沿灘企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務解決您的所有建站問題。

后果: 如果發(fā)生了數(shù)據(jù)爭用,讀取該變量時得到的值將變得不可知(根據(jù)內(nèi)存模型),使得該多線程程序的運行結(jié)果將完全不可預測,有一定可能會導致直接崩潰。

如何防止: 對于有可能被多個線程同時訪問的變量使用排他訪問控制,具體方法包括使用mutex(互斥量)或者使用atomic變量。

---------------------------------

作者注加一條規(guī)則:凡是若干線程(協(xié)程)對一個共享變量進行同步操作,且其中有一個是寫操作的,那么讀/寫都要考慮使用原子操作。

---------------------------------

race condition(競態(tài)條件)

讀取到數(shù)據(jù)中間狀態(tài)的的情形就是 race condition。相對于數(shù)據(jù)爭用(data race),競態(tài)條件(race condition)指的是更加高層次的更加復雜的現(xiàn)象,一般需要在設計并行程序時進行細致入微的分析,才能確定。(也就是隱藏得更深).

定義:受各線程上代碼執(zhí)行的順序和時機的影響,程序的運行結(jié)果產(chǎn)生(預料之外)的變化。

后果:如果存在競態(tài)條件(race condition),多次運行程序?qū)τ谕粋€輸入將會有不同的結(jié)果,但結(jié)果并非完全不可預測,它將由輸入數(shù)據(jù)和各線程的執(zhí)行順序共同決定。

如何預防:競態(tài)條件產(chǎn)生的原因很多是對于同一個資源的一系列連續(xù)操作并不是原子性的,也就是說有可能在執(zhí)行的中途被其他線程搶占,同時這個“其他線程”剛好也要訪問這個資源。解決方法通常是:將這一系列操作作為一個critical section(臨界區(qū))。

2、undefined behavior(未定義行為)

未定義行為是指執(zhí)行某種計算機代碼所產(chǎn)生的結(jié)果,這種代碼在當前程序狀態(tài)下的行為在其所使用的語言標準中沒有規(guī)定。在 Go 的內(nèi)存模型中,有race的Go程序的行為是未定義行為

3、go run/build -race(開啟race檢測)

golang在1.1之后引入了競爭檢測的概念。我們可以使用go run -race或者go build -race來進行競爭檢測。-race選項打開了data race detector用來檢查這個錯誤,而且關(guān)閉了相關(guān)的編譯器優(yōu)化(作者注:就是為了不讓編譯器優(yōu)化代碼,能看清楚完整代碼)。(原因是)go編譯器認為race代碼是dead code,可能直接優(yōu)化掉。

4、原子性

一個或者多個操作在 CPU 執(zhí)行的過程中不被中斷的特性,稱為原子性(atomicity)。這些操作對外表現(xiàn)成一個不可分割的整體,他們要么都執(zhí)行,要么都不執(zhí)行,外界不會看到他們只執(zhí)行到一半的狀態(tài)。

5、原子操作

原子操作(atomic operation)指的是由多步操作組成的一個操作。如果該操作不能原子地執(zhí)行,則要么執(zhí)行完所有步驟,要么一步也不執(zhí)行,不可能只執(zhí)行所有步驟的一個子集。

在單核系統(tǒng)里,單個的機器指令可以看成是原子操作(如果有編譯器優(yōu)化、亂序執(zhí)行等情況除外),在單核CPU中, 能夠在一個指令中完成的操作都可以看作為原子操作, 因為中斷只發(fā)生在指令間;

在多核系統(tǒng)中,單個的機器指令就不是原子操作,因為多核系統(tǒng)里是多指令流并行運行的,一個核在執(zhí)行一個指令時,其他核同時執(zhí)行的指令有可能操作同一塊內(nèi)存區(qū)域,從而出現(xiàn)數(shù)據(jù)競爭現(xiàn)象。

多核系統(tǒng)中的原子操作通常使用內(nèi)存柵障(memory barrier)來實現(xiàn),即一個CPU核在執(zhí)行原子操作時,其他CPU核必須停止對內(nèi)存操作或者不對指定的內(nèi)存進行操作,這樣才能避免數(shù)據(jù)競爭問題。

在多核CPU的時代,體系中運行著多個獨立的CPU,即使是可以在單個指令中完成的操作也可能會被干擾. 典型的例子就是decl指令(遞減指令), 它細分為三個過程: “讀->改->寫”, 涉及兩次內(nèi)存操作。如果多個CPU運行的多個進程在同時對同一塊內(nèi)存執(zhí)行這個指令,那情況是無法預測的。

二、代碼分析

race 多協(xié)程寫分析

golang在1.1之后引入了競爭檢測的概念。我們可以使用go run -race 或者 go build -race 來進行競爭檢測。

golang語言內(nèi)部大概的實現(xiàn)就是同時開啟多個goroutine執(zhí)行同一個命令,并且紀錄每個變量的狀態(tài)。

package main

import(
"time"
"fmt"
)

func main() {
a := 1
go func(){
a = 2
}()
a = 3
fmt.Println("a is ", a)

time.Sleep(2 * time.Second)
}

如果使用go run -race 1.go,將出現(xiàn)下列提示:

a is  3
==================
WARNING: DATA RACE
Write at 0x00c00012c058 by goroutine 7:
main.main.func1()
E:/hello/list/main/1.go:11 +0x44

Previous write at 0x00c00012c058 by main goroutine:
main.main()
E:/hello/list/main/1.go:13 +0x92

Goroutine 7 (running) created at:
main.main()
E:/hello/list/main/1.go:10 +0x84
==================
Found 1 data race(s)
exit status 66

這個命令輸出了WARNING:DATA RACE

總結(jié)

本篇主要介紹了一些術(shù)語,引用了一條規(guī)則:凡是多線程對共享變量涉及到寫操作,都要考慮使用原子操作。

其次,介紹了-race選項,可以對代碼涉及競態(tài)的問題做個檢查。


當前題目:Go開發(fā)競態(tài)檢測科普文
網(wǎng)站URL:http://www.dlmjj.cn/article/dpeecsg.html