如果只是讀操作,沒有寫操作,則可以不用加鎖,此種情形下,變量加上final關(guān)鍵字;
在成華等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站建設(shè)、做網(wǎng)站 網(wǎng)站設(shè)計制作按需開發(fā)網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站制作,全網(wǎng)整合營銷推廣,外貿(mào)網(wǎng)站制作,成華網(wǎng)站建設(shè)費用合理。
如果有寫操作,但是變量的寫操作跟當前的值無關(guān)聯(lián),且與其他的變量也無關(guān)聯(lián),則可考慮變量加上volatile關(guān)鍵字,同時寫操作方法通過synchronized加鎖;
sync.Map是1.9才推薦的并發(fā)安全的map,除了互斥量以外,還運用了原子操作,所以在這之前,有必要了解下 Go語言——原子操作
go1.10\src\sync\map.go
entry分為三種情況:
從read中讀取key,如果key存在就tryStore。
注意這里開始需要加鎖,因為需要操作dirty。
條目在read中,首先取消標記,然后將條目保存到dirty里。(因為標記的數(shù)據(jù)不在dirty里)
最后原子保存value到條目里面,這里注意read和dirty都有條目。
總結(jié)一下Store:
這里可以看到dirty保存了數(shù)據(jù)的修改,除非可以直接原子更新read,繼續(xù)保持read clean。
有了之前的經(jīng)驗,可以猜測下load流程:
與猜測的 區(qū)別 :
由于數(shù)據(jù)保存兩份,所以刪除考慮:
先看第二種情況。加鎖直接刪除dirty數(shù)據(jù)。思考下貌似沒什么問題,本身就是臟數(shù)據(jù)。
第一種和第三種情況唯一的區(qū)別就是條目是否被標記。標記代表刪除,所以直接返回。否則CAS操作置為nil。這里總感覺少點什么,因為條目其實還是存在的,雖然指針nil。
看了一圈貌似沒找到標記的邏輯,因為刪除只是將他變成nil。
之前以為這個邏輯就是簡單的將為標記的條目拷貝給dirty,現(xiàn)在看來大有文章。
p == nil,說明條目已經(jīng)被delete了,CAS將他置為標記刪除。然后這個條目就不會保存在dirty里面。
這里其實就跟miss邏輯串起來了,因為miss達到閾值之后,dirty會全量變成read,也就是說標記刪除在這一步最終刪除。這個還是很巧妙的。
真正的刪除邏輯:
很繞。。。。
go語言的map多協(xié)程訪問時需要加鎖
支持==和!=操作就可以做key,實際上只有function、map、slice三個kind不支持作為key,因為只能和nil比較不能和另一個值比較。布爾、整型、浮點、復(fù)數(shù)、字符串、指針、channel等都可以做key。
struct能不能做key要看每一個字段,如果所有字段都可以做key,那這個struct就可以。有一個字段不能做key,這個struct就不能做key。array也是,元素類型能做key,那這個array就可以。
例如:
type Foo map[struct {
B bool
I int
F float64
C complex128
S string
P *Foo
Ch chan Foo
}]bool
每一個字段都可以做key,F(xiàn)oo就可以做key。再如:
type Foo map[struct {
Fn func() Foo
M map[*Foo]int
S []Foo
}]bool
有一個字段不能做key、Foo就不允許做key,而這三個字段都不能。
字段是遞歸檢查的:
type Foo map[struct {
Sub struct {
M map[*Foo]bool
}
}]bool
Sub的M字段不能做key,Sub就不能做key,F(xiàn)oo也就不能做key。
總之想把一個數(shù)據(jù)結(jié)構(gòu)用于map的key,就不能包含function、map和slice。