日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

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

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
創(chuàng)新互聯(lián)GO教程:Go語言CSP:通信順序進(jìn)程簡述

Go實(shí)現(xiàn)了兩種并發(fā)形式,第一種是大家普遍認(rèn)知的多線程共享內(nèi)存,其實(shí)就是 Java 或 C++ 等語言中的多線程開發(fā);另外一種是Go語言特有的,也是Go語言推薦的 CSP(communicating sequential processes)并發(fā)模型。

CSP 并發(fā)模型是上個世紀(jì)七十年代提出的,用于描述兩個獨(dú)立的并發(fā)實(shí)體通過共享 channel(管道)進(jìn)行通信的并發(fā)模型。

Go語言就是借用 CSP 并發(fā)模型的一些概念為之實(shí)現(xiàn)并發(fā)的,但是Go語言并沒有完全實(shí)現(xiàn)了 CSP 并發(fā)模型的所有理論,僅僅是實(shí)現(xiàn)了 process 和 channel 這兩個概念。

process 就是Go語言中的 goroutine,每個 goroutine 之間是通過 channel 通訊來實(shí)現(xiàn)數(shù)據(jù)共享。

這里我們要明確的是“并發(fā)不是并行”。并發(fā)更關(guān)注的是程序的設(shè)計(jì)層面,并發(fā)的程序完全是可以順序執(zhí)行的,只有在真正的多核 CPU 上才可能真正地同時運(yùn)行;并行更關(guān)注的是程序的運(yùn)行層面,并行一般是簡單的大量重復(fù),例如 GPU 中對圖像處理都會有大量的并行運(yùn)算。

為了更好地編寫并發(fā)程序,從設(shè)計(jì)之初Go語言就注重如何在編程語言層級上設(shè)計(jì)一個簡潔安全高效的抽象模型,讓開發(fā)人員專注于分解問題和組合方案,而且不用被線程管理和信號互斥這些煩瑣的操作分散精力。

在并發(fā)編程中,對共享資源的正確訪問需要精確地控制,在目前的絕大多數(shù)語言中,都是通過加鎖等線程同步方案來解決這一困難問題,而Go語言卻另辟蹊徑,它將共享的值通過通道傳遞(實(shí)際上多個獨(dú)立執(zhí)行的線程很少主動共享資源)。

并發(fā)編程的核心概念是同步通信,但是同步的方式卻有多種。先以大家熟悉的互斥量 sync.Mutex 來實(shí)現(xiàn)同步通信,示例代碼如下所示:

package main

import (
    "fmt"
    "sync"
)

func main() {
    var mu sync.Mutex

    go func() {
        fmt.Println("C語言中文網(wǎng)")
        mu.Lock()
    }()

    mu.Unlock()
}

由于 mu.Lock() 和 mu.Unlock() 并不在同一個 Goroutine 中,所以也就不滿足順序一致性內(nèi)存模型。同時它們也沒有其他的同步事件可以參考,也就是說這兩件事是可以并發(fā)的。

因?yàn)榭赡苁遣l(fā)的事件,所以 main() 函數(shù)中的 mu.Unlock() 很有可能先發(fā)生,而這個時刻 mu 互斥對象還處于未加鎖的狀態(tài),因而會導(dǎo)致運(yùn)行時異常。

下面是修復(fù)后的代碼:

package main

import (
    "fmt"
    "sync"
)
func main() {
    var mu sync.Mutex

    mu.Lock()
    go func() {
        fmt.Println("C語言中文網(wǎng)")
        mu.Unlock()
    }()

    mu.Lock()
}

修復(fù)的方式是在 main() 函數(shù)所在線程中執(zhí)行兩次 mu.Lock(),當(dāng)?shù)诙渭渔i時會因?yàn)殒i已經(jīng)被占用(不是遞歸鎖)而阻塞,main() 函數(shù)的阻塞狀態(tài)驅(qū)動后臺線程繼續(xù)向前執(zhí)行。

當(dāng)后臺線程執(zhí)行到 mu.Unlock() 時解鎖,此時打印工作已經(jīng)完成了,解鎖會導(dǎo)致 main() 函數(shù)中的第二個 mu.Lock() 阻塞狀態(tài)取消,此時后臺線程和主線程再沒有其他的同步事件參考,它們退出的事件將是并發(fā)的,在 main() 函數(shù)退出導(dǎo)致程序退出時,后臺線程可能已經(jīng)退出了,也可能沒有退出。雖然無法確定兩個線程退出的時間,但是打印工作是可以正確完成的。

使用 sync.Mutex 互斥鎖同步是比較低級的做法,我們現(xiàn)在改用無緩存通道來實(shí)現(xiàn)同步:

package main

import (
    "fmt"
)

func main() {
    done := make(chan int)

    go func() {
        fmt.Println("C語言中文網(wǎng)")
        <-done
    }()

    done <- 1
}

根據(jù)Go語言內(nèi)存模型規(guī)范,對于從無緩存通道進(jìn)行的接收,發(fā)生在對該通道進(jìn)行的發(fā)送完成之前。因此,后臺線程
<-done 接收操作完成之后,main 線程的
done <- 1 發(fā)送操作才可能完成(從而退出 main、退出程序),而此時打印工作已經(jīng)完成了。

上面的代碼雖然可以正確同步,但是對通道的緩存大小太敏感,如果通道有緩存,就無法保證 main() 函數(shù)退出之前后臺線程能正常打印了,更好的做法是將通道的發(fā)送和接收方向調(diào)換一下,這樣可以避免同步事件受通道緩存大小的影響:

package main

import (
    "fmt"
)

func main() {
    done := make(chan int, 1) // 帶緩存通道

    go func() {
        fmt.Println("C語言中文網(wǎng)")
        done <- 1
    }()

    <-done
}

對于帶緩存的通道,對通道的第 K 個接收完成操作發(fā)生在第 K+C 個發(fā)送操作完成之前,其中 C 是通道的緩存大小。雖然通道是帶緩存的,但是 main 線程接收完成是在后臺線程發(fā)送開始但還未完成的時刻,此時打印工作也是已經(jīng)完成的。

基于帶緩存通道,我們可以很容易將打印線程擴(kuò)展到 N 個,下面的示例是開啟 10 個后臺線程分別打?。?br />

package main

import (
    "fmt"
)

func main() {
    done := make(chan int, 10) // 帶10個緩存

    // 開N個后臺打印線程
    for i := 0; i < cap(done); i++ {
        go func() {
            fmt.Println("C語言中文網(wǎng)")
            done <- 1
        }()
    }

    // 等待N個后臺線程完成
    for i := 0; i < cap(done); i++ {
        <-done
    }
}

對于這種要等待 N 個線程完成后再進(jìn)行下一步的同步操作有一個簡單的做法,就是使用 sync.WaitGroup 來等待一組事件:

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup

    // 開N個后臺打印線程
    for i := 0; i < 10; i++ {
        wg.Add(1)

        go func() {
            fmt.Println("C語言中文網(wǎng)")
            wg.Done()
        }()
    }

    // 等待N個后臺線程完成
    wg.Wait()
}

其中 wg.Add(1) 用于增加等待事件的個數(shù),必須確保在后臺線程啟動之前執(zhí)行(如果放到后臺線程之中執(zhí)行則不能保證被正常執(zhí)行到)。當(dāng)后臺線程完成打印工作之后,調(diào)用 wg.Done() 表示完成一個事件,main() 函數(shù)的 wg.Wait() 是等待全部的事件完成。


分享標(biāo)題:創(chuàng)新互聯(lián)GO教程:Go語言CSP:通信順序進(jìn)程簡述
當(dāng)前網(wǎng)址:http://www.5511xx.com/article/cojijip.html