自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

三分鐘掌握Actor和CSP模型

開發(fā) 前端
本文現(xiàn)在要記錄的是另一種基于消息傳遞的并發(fā)模型:CSP(communicating sequential process順序通信過程)。

go的CSP模型

  • 傳統(tǒng)多線程的的共享內(nèi)存(ShareMemory)模型使用lock,condition等同步原語來強行規(guī)定進程的執(zhí)行順序。
  • Actor模型,是基于消息傳遞的并發(fā)模型, 強調(diào)的是Actor這個工作實體,每個Actor自行決定消息傳遞的方向(要傳遞的ActorB),通過消息傳遞形成流水線。

本文現(xiàn)在要記錄的是另一種基于消息傳遞的并發(fā)模型:CSP(communicating sequential process順序通信過程)。

在CSP模型,worker之間不直接彼此聯(lián)系,強調(diào)信道在消息傳遞中的作用,不謀求形成流水線。

消息的發(fā)送者和接受者通過該信道松耦合,發(fā)送者不知道自己消息被哪個接受者消費了,接受者也不知道是從哪個發(fā)送者發(fā)送的消息。

go的信道

go的信道[1]是golang協(xié)程同步和通信的原生方式。

同map,slice一樣,channel通過make內(nèi)置函數(shù)初始化并返回引用,引用可認為是常量指針[2]。

兩種信道:

1. 無緩沖區(qū)信道:讀寫兩端就緒后,才能通信(一方?jīng)]就緒就阻塞)。

這種方式可以用來在goroutine中進行同步,而不必顯式鎖或者條件變量。

2. 有緩沖區(qū)信道:就有可能不阻塞, 只有buffer滿了,寫入才會阻塞;只有buffer空了,讀才會阻塞。

go的信道暫時先聊到這里。

我們來用以上背景做一道 有意思的面試題吧 。

兩個線程輪流打印0到100?

我不會啥算法,思路比較弱智:#兩線程#, #打印奇/偶數(shù)#, 我先復(fù)刻這兩個標簽。

通過go的無緩沖信道的同步阻塞的能力對齊每一次循環(huán)。

package main

import (
"fmt"
"strconv"
"sync"
)

var wg sync.WaitGroup
var ch1 = make(chan struct{})

func main() {
wg.Add(2)

go func() {
defer wg.Done()
for i := 0; i <= 100; i++ {
ch1 <- struct{}{}
if i%2 == 0 { // 偶數(shù)
fmt.Println("g0 " + strconv.Itoa(i))
}
}
}()

go func() {
defer wg.Done()
for i := 0; i <= 100; i++ {
<-ch1
if i%2 == 1 { // 奇數(shù)
fmt.Println("g1 " + strconv.Itoa(i))
}
}
}()
wg.Wait()
}

題解:兩個協(xié)程都執(zhí)行0到100次循環(huán),但是不管哪個線程跑的快,在每次循環(huán)輸出時均會同步對齊, 每次循環(huán)時只輸出一個奇/偶值, 這樣也不用考慮兩個協(xié)程的啟動順序。

思考我的老牌勁語C#要完成本題要怎么做?

依舊是#兩線程#、#打印奇偶數(shù)#, 我沒找到C#中能多次對齊線程的能力, 于是使用兩線程相互通知的方式。

volatile static int i = 0;

static AutoResetEvent are = new AutoResetEvent(true);
static AutoResetEvent are2 = new AutoResetEvent(false);
public static void Main(String[] args)
{
Thread thread1 = new Thread(() =>
{
for (var i=0;i<=100;i++)
{
are.WaitOne();
if (i % 2 == 0)
{
Console.WriteLine(i + "== 偶數(shù)");
}
are2.Set();
}
});
Thread thread2 = new Thread(() =>
{
for (var i = 0; i <= 100; i++)
{
are2.WaitOne();
if (i % 2 == 1)
{
Console.WriteLine(i + "== 奇數(shù)");
}
are.Set();
}
});

thread1.Start();
thread2.Start();
Console.ReadKey();
}

注意:

  • volatile:提醒編譯器或運行時系統(tǒng)不對字段做優(yōu)化(處于性能性能,編譯器/runtime會對同時執(zhí)行的線程訪問的同一字段進行優(yōu)化,加volatile忽略這種優(yōu)化 )。
  • Object-->MarshalByRefObject-->WaitHandle-->EventWaitHandle--->AutoResetEvent[3] 本次使用了2個自動重置事件來切換通知,由一個線程通知另外一個線程執(zhí)行。

引用鏈接

[1] go的信道: https://www.runoob.com/w3cnote/go-channel-intro.html

[2] 常量指針: https://zhuanlan.zhihu.com/p/133225100

[3] AutoResetEvent: https://docs.microsoft.com/en-us/dotnet/api/system.threading.autoresetevent?view=net-6.0

責任編輯:武曉燕 來源: 精益碼農(nóng)
相關(guān)推薦

2021-12-17 07:47:37

IT風(fēng)險框架

2025-02-13 08:04:49

spliceCPU數(shù)據(jù)

2024-07-05 09:31:37

2024-05-16 11:13:16

Helm工具release

2023-12-04 18:13:03

GPU編程

2009-11-09 12:55:43

WCF事務(wù)

2024-12-18 10:24:59

代理技術(shù)JDK動態(tài)代理

2021-04-20 13:59:37

云計算

2023-12-27 08:15:47

Java虛擬線程

2024-01-16 07:46:14

FutureTask接口用法

2022-02-17 09:24:11

TypeScript編程語言javaScrip

2024-08-30 08:50:00

2017-11-20 10:37:03

2020-08-17 17:20:36

pythonJAVA代碼

2013-06-28 14:30:26

棱鏡計劃棱鏡棱鏡監(jiān)控項目

2020-06-30 10:45:28

Web開發(fā)工具

2017-11-20 10:35:36

2021-10-20 17:44:57

分析模型回歸

2009-10-29 16:22:10

VB.NET操作MyS

2025-04-01 01:25:00

MySQLInnoDBMyISAM
點贊
收藏

51CTO技術(shù)棧公眾號