美文网首页
erlang actor和 go cas

erlang actor和 go cas

作者: Wu杰语 | 来源:发表于2021-09-08 00:07 被阅读0次

语言是技术栈的基础,语言中往往体现了重要的设计思想。erlang和go是两种比较特殊的我喜欢的语言,erlang是面向线程的反映世界的语言,主要是函数式;而go则是集c、c++、java、haskel等语言长处为一体的语言,本文主要对照一下两种语言并发通信的原理。

轻量级线程

erlang和go都实现了用户态的调度,都是轻量级协程,go的调度见《go runtime和java jvm》一文。

actor

actor是什么,actor就是消息的方式进行通信,对于每个erlang线程,都有一个消息队列用于存储消息。

-module(tut15).

-export([start/0, ping/2, pong/0]).

ping(0, Pong_PID) ->
    Pong_PID ! finished,
    io:format("ping finished~n", []);

ping(N, Pong_PID) ->
    Pong_PID ! {ping, self()},
    receive
        pong ->
            io:format("Ping received pong~n", [])
    end,
    ping(N - 1, Pong_PID).

pong() ->
    receive
        finished ->
            io:format("Pong finished~n", []);
        {ping, Ping_PID} ->
            io:format("Pong received ping~n", []),
            Ping_PID ! pong,
            pong()
    end.

start() ->
    Pong_PID = spawn(tut15, pong, []),
    spawn(tut15, ping, [3, Pong_PID]).

例如这段代码, 启动了2个erlang线程,pong线程启动的时候记录pid,传递给ping线程,pid ! message表示把消息传递给pid的线程,而消息处理用receive来处理,就是一个典型的消息队列处理,所以整个erlang的吞吐效率非常高。

go cas

go的cas是强调通信信道,可以参照Go channel 实现原理分析 - 简书 (jianshu.com)

type hchan struct {
       qcount   uint           // total data in the queue 当前队列里还剩余元素个数
       dataqsiz uint           // size of the circular queue 环形队列长度,即缓冲区的大小,即make(chan T,N) 中的N
       buf      unsafe.Pointer // points to an array of dataqsiz elements 环形队列指针
       elemsize uint16 //每个元素的大小
       closed   uint32 //标识当前通道是否处于关闭状态,创建通道后,该字段设置0,即打开通道;通道调用close将其设置为1,通道关闭
       elemtype *_type // element type 元素类型,用于数据传递过程中的赋值
       sendx    uint   // send index 环形缓冲区的状态字段,它只是缓冲区的当前索引-支持数组,它可以从中发送数据
       recvx    uint   // receive index 环形缓冲区的状态字段,它只是缓冲区当前索引-支持数组,它可以从中接受数据
       recvq    waitq  // list of recv waiters 等待读消息的goroutine队列
       sendq    waitq  // list of send waiters 等待写消息的goroutine队列
    
       // lock protects all fields in hchan, as well as several
       // fields in sudogs blocked on this channel.
       //
       // Do not change another G's status while holding this lock
       // (in particular, do not ready a G), as this can deadlock
       // with stack shrinking.
       lock mutex //互斥锁,为每个读写操作锁定通道,因为发送和接受必须是互斥操作
  }
  
  // sudog 代表goroutine
   type waitq struct {
        first *sudog
        last  *sudog
  }

其中channel的实现特别需要留意,消息的存储在buf中,这里是一个环形队列的设计,使用环形队列控制大小和发送、消费的机制;使用channel的发送队列保存在recvq,消费队列保存在sendq中,了解了这些基本就可以推测出channel的工作机制了,和生产者消费者就是一个原理。

小结

ACTOR和CAS是非常有意思的两种线程通信机制,各有所长,你更喜欢哪种设计?其中akaka就是jvm系列的actor。

相关文章

网友评论

      本文标题:erlang actor和 go cas

      本文链接:https://www.haomeiwen.com/subject/fsemwltx.html