# 結構體知識小問題
* * * * *
--: 作者:Mick
時間:2018年11月18日
* * * * *
### 概念理解
1:并發的關鍵是你有處理多個任務的能力,一件一件間隔的完成
你吃飯吃到一半,電話來了,你停了下來接了電話,接完后繼續吃飯,這說明你支持并發。??(不一定是同時的)
2:并行的關鍵是你有同時處理多個任務的能力
你吃飯吃到一半,電話來了,你一邊打電話一邊吃飯,這說明你支持并行??

#### 實例展示
思考邏輯處理器:多少是并發?多少是并行?
```
func main(){
runtime.GOMAXPROCS(1)
var wg sync.WaitGroup
wg.Add(2)
go onCpuNum("A",&wg)
go onCpuNum("B",&wg)
wg.Wait()
}
//并發輸出5000以內的素數
func onCpuNum(pre string,wg *sync.WaitGroup){
defer wg.Done()
next:
for i:=2;i<5000;i++{
for j:=2;j<i;j++{
if i%j == 0{
continue next
}
}
fmt.Printf("%s:%d\n",pre,i)
}
}
```
### 并發導致鎖問題
```
func race(){
var num int
var wg sync.WaitGroup
wg.Add(2)
go func(){
defer wg.Done()
for i:=0;i<10000;i++{
num++
}
}()
go func(){
defer wg.Done()
for i:=0;i<10000;i++{
num++
}
}()
wg.Wait()
fmt.Println(num)
}
```
### 解決方案
加鎖:鎖住共享資源,原子函數與互斥鎖
通道:在goroutinue之間傳遞數據的類型,采用通信順序進程(CSP)模型進行通信
#### 原子函數
累加函數:atomic.AddInt64(addr *int64, delta int64) (new int64)
寫函數: atomic.StoreInt64(addr *int64, val int64)
讀函數 : atomic.LoadInt64(addr *int64) (val int64)
請使用上述函數對競狀態函數進行改造???
原子函數示例
```
func atomicStoreLoad(){
var wg sync.WaitGroup
var shutdown int64
wg.Add(2)
go func(){
defer wg.Done()
for {
fmt.Println("Doing jack work")
time.Sleep(time.Millisecond*250)
if atomic.LoadInt64(&shutdown) == 1 {
fmt.Println("Shutdown jack work")
break
}
}
}()
go func(){
defer wg.Done()
for {
fmt.Println("Doing tom work")
time.Sleep(time.Millisecond*250)
if atomic.LoadInt64(&shutdown) == 1 {
fmt.Println("Shutdown tom work")
break
}
}
}()
time.Sleep(time.Second)
fmt.Println("shutdown now")
atomic.StoreInt64(&shutdown,1)
wg.Wait()
}
```
#### 互斥鎖
sync.Mutex結構體是對原子函數的封裝實現區域保護
```
func mutexLock(){
var wg sync.WaitGroup
var num int
var mutex sync.Mutex
wg.Add(2)
go func(){
for i:=0;i<10000;i++{
mutex.Lock()
num++
mutex.Unlock()
}
defer wg.Done()
}()
go func(){
for i:=0;i<10000;i++{
mutex.Lock()
num++
mutex.Unlock()
}
defer wg.Done()
}()
wg.Wait()
fmt.Println(num)
}
```
## 存在問題,解決了資源的安全訪問以及消除競爭狀態,但是goroutinue之間怎么通信(傳遞變量) ???
### 通道