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

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

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
單線程是不是go語言的特性

這篇文章主要介紹“單線程是不是go語言的特性”,在日常操作中,相信很多人在單線程是不是go語言的特性問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”單線程是不是go語言的特性”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

創(chuàng)新互聯(lián)建站堅持“要么做到,要么別承諾”的工作理念,服務領域包括:網(wǎng)站設計制作、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務,滿足客戶于互聯(lián)網(wǎng)時代的廣州網(wǎng)站設計、移動媒體設計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡建設合作伙伴!

單線程不是go語言的特性,go語言是多線程的。Golang的線程模型是MPG模型,整體上Go程與內核線程是多對多對應的,因此Go一定是多線程模式的;其中M與內核線程是1比1對應,然后多個G與多個M對應,P指的是上下文資源。

單線程不是go語言的特性,go語言是多線程的。

Golang 的線程模型是 M P G 模型,整體上 Go 程與內核線程是多對多對應的,因此首先來講就一定是多線程的。其中 M 與內核線程是1比1對應,然后多個 G 與多個 M 對應,P 指的是上下文資源,不多說。M 的數(shù)量(或者說內核線程)什么時候增加呢?就是在當前的 M 數(shù)量無法調度得動當前所有 G 的時候就起新的 M 來處理。

Go 并發(fā)(多線程)

有人把Go比作21世紀的C語言,第一是因為Go語言設計簡單,第二,21世紀最重要的就是并行程序設計,而Go從語言層面就支持了并行。

goroutine

goroutine是Go并行設計的核心。goroutine說到底其實就是線程,但是它比線程更小,十幾個goroutine可能體現(xiàn)在底層就是五六個線程,Go語言內部幫你實現(xiàn)了這些goroutine之間的內存共享。執(zhí)行goroutine只需極少的棧內存(大概是4~5KB),當然會根據(jù)相應的數(shù)據(jù)伸縮。也正因為如此,可同時運行成千上萬個并發(fā)任務。goroutine比thread更易用、更高效、更輕便。

goroutine是通過Go的runtime管理的一個線程管理器。goroutine通過go關鍵字實現(xiàn)了,其實就是一個普通的函數(shù)。

go hello(a, b, c)

通過關鍵字go就啟動了一個goroutine。我們來看一個例子

package main

import (
    "fmt"
    "runtime"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        runtime.Gosched()
        fmt.Println(s)
    }
}

func main() {
    go say("world") //開一個新的Goroutines執(zhí)行
    say("hello") //當前Goroutines執(zhí)行
}

// 以上程序執(zhí)行后將輸出:
// hello
// world
// hello
// world
// hello
// world
// hello
// world
// hello

我們可以看到go關鍵字很方便的就實現(xiàn)了并發(fā)編程。 上面的多個goroutine運行在同一個進程里面,共享內存數(shù)據(jù),不過設計上我們要遵循:不要通過共享來通信,而要通過通信來共享。

runtime.Gosched()表示讓CPU把時間片讓給別人,下次某個時候繼續(xù)恢復執(zhí)行該goroutine。

默認情況下,調度器僅使用單線程,也就是說只實現(xiàn)了并發(fā)。想要發(fā)揮多核處理器的并行,需要在我們的程序中顯式調用 runtime.GOMAXPROCS(n) 告訴調度器同時使用多個線程。GOMAXPROCS 設置了同時運行邏輯代碼的系統(tǒng)線程的最大數(shù)量,并返回之前的設置。如果n < 1,不會改變當前設置。以后Go的新版本中調度得到改進后,這將被移除。

channels

goroutine運行在相同的地址空間,因此訪問共享內存必須做好同步。那么goroutine之間如何進行數(shù)據(jù)的通信呢,Go提供了一個很好的通信機制channel。channel可以與Unix shell 中的雙向管道做類比:可以通過它發(fā)送或者接收值。這些值只能是特定的類型:channel類型。定義一個channel時,也需要定義發(fā)送到channel的值的類型。注意,必須使用make 創(chuàng)建channel:

ci := make(chan int)
cs := make(chan string)
cf := make(chan interface{})

channel通過操作符<-來接收和發(fā)送數(shù)據(jù)

ch <- v    // 發(fā)送v到channel ch.
v := <-ch  // 從ch中接收數(shù)據(jù),并賦值給v

我們把這些應用到我們的例子中來:

package main

import "fmt"

func sum(a []int, c chan int) {
    total := 0
    for _, v := range a {
        total += v
    }
    c <- total  // send total to c
}

func main() {
    a := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int)
    go sum(a[:len(a)/2], c)
    go sum(a[len(a)/2:], c)
    x, y := <-c, <-c  // receive from c

    fmt.Println(x, y, x + y)
}

默認情況下,channel接收和發(fā)送數(shù)據(jù)都是阻塞的,除非另一端已經(jīng)準備好,這樣就使得Goroutines同步變的更加的簡單,而不需要顯式的lock。所謂阻塞,也就是如果讀?。╲alue := <-ch)它將會被阻塞,直到有數(shù)據(jù)接收。其次,任何發(fā)送(ch<-5)將會被阻塞,直到數(shù)據(jù)被讀出。無緩沖channel是在多個goroutine之間同步很棒的工具。

Buffered Channels

上面我們介紹了默認的非緩存類型的channel,不過Go也允許指定channel的緩沖大小,很簡單,就是channel可以存儲多少元素。ch:= make(chan bool, 4),創(chuàng)建了可以存儲4個元素的bool 型channel。在這個channel 中,前4個元素可以無阻塞的寫入。當寫入第5個元素時,代碼將會阻塞,直到其他goroutine從channel 中讀取一些元素,騰出空間。

ch := make(chan type, value)

value == 0 ! 無緩沖(阻塞)
value > 0 ! 緩沖(非阻塞,直到value 個元素)

我們看一下下面這個例子,你可以在自己本機測試一下,修改相應的value值

package main

import "fmt"

func main() {
    c := make(chan int, 2)//修改2為1就報錯,修改2為3可以正常運行
    c <- 1
    c <- 2
    fmt.Println(<-c)
    fmt.Println(<-c)
}
    //修改為1報如下的錯誤:
    //fatal error: all goroutines are asleep - deadlock!

Range和Close

上面這個例子中,我們需要讀取兩次c,這樣不是很方便,Go考慮到了這一點,所以也可以通過range,像操作slice或者map一樣操作緩存類型的channel,請看下面的例子

package main

import (
    "fmt"
)

func fibonacci(n int, c chan int) {
    x, y := 1, 1
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x + y
    }
    close(c)
}

func main() {
    c := make(chan int, 10)
    go fibonacci(cap(c), c)
    for i := range c {
        fmt.Println(i)
    }
}

for i := range c能夠不斷的讀取channel里面的數(shù)據(jù),直到該channel被顯式的關閉。上面代碼我們看到可以顯式的關閉channel,生產(chǎn)者通過內置函數(shù)close關閉channel。關閉channel之后就無法再發(fā)送任何數(shù)據(jù)了,在消費方可以通過語法v, ok := <-ch測試channel是否被關閉。如果ok返回false,那么說明channel已經(jīng)沒有任何數(shù)據(jù)并且已經(jīng)被關閉。

記住應該在生產(chǎn)者的地方關閉channel,而不是消費的地方去關閉它,這樣容易引起panic

另外記住一點的就是channel不像文件之類的,不需要經(jīng)常去關閉,只有當你確實沒有任何發(fā)送數(shù)據(jù)了,或者你想顯式的結束range循環(huán)之類的

Select

我們上面介紹的都是只有一個channel的情況,那么如果存在多個channel的時候,我們該如何操作呢,Go里面提供了一個關鍵字select,通過select可以監(jiān)聽channel上的數(shù)據(jù)流動。

select默認是阻塞的,只有當監(jiān)聽的channel中有發(fā)送或接收可以進行時才會運行,當多個channel都準備好的時候,select是隨機的選擇一個執(zhí)行的。

package main

import "fmt"

func fibonacci(c, quit chan int) {
    x, y := 1, 1
    for {
        select {
        case c <- x:
            x, y = y, x + y
        case <-quit:
            fmt.Println("quit")
            return
        }
    }
}

func main() {
    c := make(chan int)
    quit := make(chan int)
    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println(<-c)
        }
        quit <- 0
    }()
    fibonacci(c, quit)
}

select里面還有default語法,select其實就是類似switch的功能,default就是當監(jiān)聽的channel都沒有準備好的時候,默認執(zhí)行的(select不再阻塞等待channel)。

select {
case i := <-c:
    // use i
default:
    // 當c阻塞的時候執(zhí)行這里
}

超時

有時候會出現(xiàn)goroutine阻塞的情況,那么我們如何避免整個程序進入阻塞的情況呢?我們可以利用select來設置超時,通過如下的方式實現(xiàn):

func main() {
    c := make(chan int)
    o := make(chan bool)
    go func() {
        for {
            select {
                case v := <- c:
                    println(v)
                case <- time.After(5 * time.Second):
                    println("timeout")
                    o <- true
                    break
            }
        }
    }()
    <- o
}

runtime goroutine

runtime包中有幾個處理goroutine的函數(shù):

  • Goexit

    退出當前執(zhí)行的goroutine,但是defer函數(shù)還會繼續(xù)調用

  • Gosched

    讓出當前goroutine的執(zhí)行權限,調度器安排其他等待的任務運行,并在下次某個時候從該位置恢復執(zhí)行。

  • NumCPU

    返回 CPU 核數(shù)量

  • NumGoroutine

    返回正在執(zhí)行和排隊的任務總數(shù)

  • GOMAXPROCS

    用來設置可以并行計算的CPU核數(shù)的最大值,并返回之前的值。

到此,關于“單線程是不是go語言的特性”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
分享標題:單線程是不是go語言的特性
分享URL:http://www.dlmjj.cn/article/gipcpe.html