專注於網路程式設計,遊戲後臺,高併發
go語言天生支援高併發,同時訪問幾千幾萬網頁不是問題。例如在寫網路爬蟲時,我們從根頁面找出其他的頁面,然後其他的頁面又找出其他的頁面,如此反覆。雖然go可以支援同時訪問那麼多頁面,但是作業系統卻不支援同時開啟那麼多頁面,因為每次訪問頁面都是一次socket通訊。每次socket通訊就會佔用檔案描述符fd,作業系統同時支援開啟的fd是有限制的。所以有必要做併發控制。
下面模擬爬蟲的實驗。有一個函式每次隨機產生0-30個int型陣列。對陣列遍歷時又根據那個函式產生隨機陣列。我們先看看不做併發控制的程式碼:
package main import ( "fmt" "time" "math/rand" "sync/atomic" ) var Sum int32 = 0 //當前開啟fd的總量 func produceInt() []int { defer func() { atomic.AddInt32(&Sum, -1) }() atomic.AddInt32(&Sum, 1) rnd := rand.Intn(30) //這次產生的int的數量 var list []int for i := 0; i < rnd; i++ { list = append(list, rand.Intn(100)) } time.Sleep(time.Millisecond * 100) return list } func main() { workList := make(chan []int) go func() { workList <- []int{1} }() go func() { for { fmt.Println("\nsum is ", Sum) //列印當前fd的數量 time.Sleep(time.Second) } }() for list := range workList { //list仍然是個[]int for range list { go func() { workList <- produceInt() }() } } }
運行當前的程式碼,發現fd是一直不停的在增加的。我們開始想辦法控制併發。
最簡單的方法就是利用chan來實現:
package main import ( "fmt" "time" "math/rand" "sync/atomic" ) var Sum int32 = 0 //當前開啟fd的總量 var tokens = make(chan struct{}, 30) func produceInt() []int { defer func() { atomic.AddInt32(&Sum, -1) }() tokens <- struct{}{} //用chan同步來控制 atomic.AddInt32(&Sum, 1) rnd := rand.Intn(30) //這次產生的int的數量 var list []int for i := 0; i < rnd; i++ { list = append(list, rand.Intn(100)) } time.Sleep(time.Millisecond * 100) <- tokens return list } func main() { workList := make(chan []int) go func() { workList <- []int{1} }() go func() { for { fmt.Println("\nsum is ", Sum) //列印當前fd的數量 time.Sleep(time.Second) } }() for list := range workList { //list仍然是個[]int for range list { go func() { workList <- produceInt() }() } } }
另外一種寫法就是,利用chan,每次只取陣列元素中的一個。然後開啟N個這樣的協程,程式碼如下:
package main import ( "fmt" "time" "math/rand" "sync/atomic" "runtime" ) var Sum int32 = 0 //當前開啟fd的總量 func produceInt() []int { defer func() { atomic.AddInt32(&Sum, -1) }() atomic.AddInt32(&Sum, 1) rnd := rand.Intn(30) //這次產生的int的數量 var list []int for i := 0; i < rnd; i++ { list = append(list, rand.Intn(100)) } time.Sleep(time.Millisecond * 100) return list } func main() { workList := make(chan []int) unseen := make(chan int) go func() { for { fmt.Printf("sum is %d", Sum) //列印當前fd的數量 fmt.Printf("num of co is %d\n", runtime.NumGoroutine()) //當前協程的數量 time.Sleep(time.Second) } }() go func() { workList <- []int{1} }() for i := 0; i < 20; i++ { go func() { for range unseen { k := produceInt() go func() { workList <- k }() } }() } for list := range workList { for _, l := range list { unseen <- l } } }
注意,雖然併發得到了控制,但是協程的數量是一直在增加的,執行第三個程式碼就可以看。
相關推薦
專注於網路程式設計,遊戲後臺,高併發
go語言天生支援高併發,同時訪問幾千幾萬網頁不是問題。例如在寫網路爬蟲時,我們從根頁面找出其他的頁面,然後其他的頁面又找出其他的頁面,如此反覆。雖然go可以支援同時訪問那麼多頁面,但是作業系統卻不支援同時開啟那麼多頁面,因為每次訪問頁面都是一次socket通訊。每次socke
Linux學習之網路程式設計(多程序併發伺服器)
言之者無罪,聞之者足以戒。 - “詩序” 上面我們所說過的通訊都是一個伺服器一個客戶端之間的通訊,下面我們來交流一下多程序併發伺服器的相關知識 邏輯上就是這個樣子的,就是一個伺服器多個客戶端進行資料的傳輸。 1、傳送資料的函式: ssize_t send(int sockfd,
linux網路程式設計之多程序併發伺服器
1)使用多程序併發伺服器考慮的因素: (1)父程序描述最大檔案描述符的個數(父程序需要關閉accept返回的新檔案描述符) (2)系統內可建立程序的個數(與記憶體大小相關) (3)程序建立過多是否降低整體服務效能 2)多程序建立併發
嵌入式Linux網路程式設計,TCP多併發伺服器,TCP多執行緒併發伺服器,TCP多程序併發伺服器
文章目錄 1,TCP多執行緒併發伺服器 1.1,標頭檔案net.h 1.2,客戶端client.c 1.3,伺服器端server.c 2,TCP多程序併發伺服器 2.1,標頭檔案net.h 2.2,客
Java併發程式設計入門與高併發面試
第6章 J.U.C之AQS講解 AQS是J.U.C的重要元件,也是面試的重要考點。這一章裡將重點講解AQS模型設計及相關同步元件的原理和使用,都非常實用,具體包括:CountDownLatch、Semaphore、CyclicBarrier、ReentrantLock與鎖、Condition等。這些元
flylkly的小窩[專注於網路安全]
若一臺計算機的字長為32位,則表明該計算機 ( ) A : 能處理的數值最大為4位十進位制數 B : 能處理的數值最多為4個位元組 C : 在CPU中能夠作為一個整體加以處理的二進位制資料為4個位元組 D : CPU中運算的結果最大為232 答案是C 解說: 字長是指微
非同步程式設計CompletableFuture實現高併發系統優化之請求合併
先說場景: 根據Redis官網介紹,單機版Redis的讀寫效能是12萬/秒,批量處理可以達到70萬/秒。不管是快取或者是資料庫,都有批量處理的功能。當我們的系統達到瓶頸的時候,我們考慮充分的壓榨快取和資料庫的效能,應對更大的併發請求。適用於電商促銷雙十一,等特定高併發的場景,讓系統可以支撐更高的併發
linux 高併發網路程式設計之epoll詳解
前言 I/O多路複用有很多種實現。在linux上,2.4核心前主要是select和poll,自Linux 2.6核心正式引入epoll以來,epoll已經成為了目前實現高效能網路伺服器的必備技術。儘管他們的使用方法不盡相同,但是本質上卻沒有什麼區別。本文將重點探
Python高併發的網路程式設計庫:eventlet
eventlet是一個用來處理和網路相關的python庫函式,而且可以通過協程來實現併發,在eventlet裡,把“協程”叫做 greenthread(綠色執行緒)。所謂併發,就是開啟了多個greenthread,並且對這些greenthread進行管理,以實現非阻塞式的
Linux IO多路複用之epoll網路程式設計,高併發的使用例子 (含原始碼)
#include <unistd.h> #include <sys/types.h> /* basic system data types */ #include <sys/socket.h> /* basic socket definiti
HttpClient客戶端網路程式設計——高可用、高併發
本文是HttpClient的學習部落格,RestTemplate是基於HttpClient的封裝,feign可基於HttpClient進行網路通訊。 那麼作為較底層的客戶端網路程式設計框架,該怎麼配置使其能高可用,高併發,可支援Https協議呢?通讀本文也許你會有答案或者啟發。 本文是Maven專
實戰Java高併發程式設計.epub
【下載地址】 在過去單核CPU時代,單任務在一個時間點只能執行單一程式,隨著多核CPU的發展,並行程式開發就顯得尤為重要。 《實戰Java高併發程式設計》主要介紹基於Java的並行程式設計基礎、思路、方法和實戰。第一,立足於併發程式基礎,詳細介紹Ja
高併發程式設計:同步類容器的問題
同步容器類存在的問題 同步類容器都是執行緒安全的,但在某些場景下可能需要加鎖來保護複合操作,在複合操作,如:迭代、跳轉已經條件運算中,這些操作可能會表現出意外的行為,最經典的便是ConcurrentModificationException,原因是當容器迭代的過程中,被併發的修改了內
高併發程式設計:併發Queue介面
佇列是一種先進先出或者後進後出的資料結構。在此我們模擬一下佇列這種資料結構: MyQueue.java定義如下: public class MyQueue { //佇列的容器 private LinkedList<Object> list = new L
高併發程式設計:初識併發容器類
JDK5.0以後提供了多種併發類容器來替代同步容器類從而改善效能。同步類容器狀態都是序列化的。他們雖然實現了執行緒安全,但是嚴重降低了併發性,在多執行緒環境時,嚴重降低了應用程式的吞吐量。 ConcurrentMap介面 ConcurrentMap介面有兩個重要的實現類:Conc
高併發程式設計:執行緒安全和ThreadLocal
執行緒安全的概念:當多個執行緒訪問某一個類(物件或方法)時,這個類始終都能表現出正確的行為,那麼這個類(物件或方法)就是執行緒安全的。 執行緒安全 說的可能比較抽象,下面就以一個簡單的例子來看看什麼是執行緒安全問題。 public class MyThread impleme
2018最新實戰Java高併發程式設計
在過去單核CPU時代,單任務在一個時間點只能執行單一程式,隨著多核CPU的發展,並行程式開發就顯得尤為重要。《實戰Java高併發程式設計》主要介紹基於Java的並行程式設計基礎、思路、方法和實戰。第一,立足於併發程式基礎,詳細介紹Java中進行並行程式設計的基本方法。第二,進一步詳細介紹JDK中對並
淺談高併發程式設計
1、首先考慮分散式,業務功能服務化 使用阿里的dubbo框架,使用zookeeper作為註冊中心;或者spring cloud等;系統靈活部署,在真正消耗資源的服務上,考慮增加例項。 2、打薄閘道器層 &
高併發程式設計 volatile 和 加鎖 解決快取不一致
因為程式執行都在cpu中,但是如果沒有快取記憶體,cpu大部分的時間都用來了讀取記憶體的資料。 從而Cpu有 快取記憶體,在執行指令前,會把相關需要的資料提前拷貝到cpu,運算完成後在刷回記憶體裡。 快取記憶體主要提前快取資料到cpu,等cpu運算完成後把結果返回給主存
仿微信 IM後臺(億級流量高併發) 瘋狂實戰
仿微信 億級流量 IM後臺 實戰 分散式、高併發、億級流量—— 瘋狂創客圈 死磕Netty 系列之10 億級流量IM的應用場景 隨著移動網際網路、AI的飛速發展,高效能高併發IM(即時通訊),有著非常廣泛的應用場景。 一切高實