csp 通道 计时器 依赖管理

82 阅读4分钟

csp

CSP(Communicating Sequential Processes)是Go语言并发模型的基础,有两种实现方式:

  1. 通信共享内存:通过通道(channel)进行通信,保证顺序。
  2. 共享内存实现通信:通过加锁等方式实现共享内存的访问。

Go语言更推荐使用通道来进行通信,因为这种方式更安全、更易于管理。

分两种,

0

第一种涉及到一个重要的概念,叫做通道

把协程做了个连接,来保证顺序

第二种必须是通过物质量对内存进行一个加锁,需要获得临界区的一个权限,在这种机制下不同的空间就容易发生数据静态的问题,就是一定程度上会影响程序的性能

通过两个的对比,go语言提倡用第一种来实现共享内存

通道

通道分为两种一种是无缓冲通道,一种是有缓冲通道

make(chan 元素类型,[缓冲大小])

根据是否有缓冲区的大小来判断有无缓冲通道

无缓冲通道 make(chan int),被称为同步通道

有缓冲通道 make(chan int, 2)

通道的容量,代表通道能存放多少元素了,类比于学校的仓库的格子,是有限的,如果格子满了就装不下了,这种情况下会发生阻塞发送,知道有人取走才能继续放下去

具体使用

0

消费者的消费速度比打印可能更加复杂

消费者的消费速度可能相对慢一些

生产者的逻辑相对简单可能相对较快

我们用带缓冲的一个队列(通道)就不会因为消费者的一个问题来影响整个的一个效率

我们每一个channel都用了defer做了一个延迟的资源关闭

通道可以用于生产者-消费者模式,确保生产者和消费者之间的数据同步。例如:

go

func producer(ch chan 

int) {

    for i := 0; i < 

    5; i++ {

        ch <- i

    }

    close(ch)

}

func consumer(ch chan 

int) {

    for num := range 

    ch {

        fmt.Println

        ("Consumed:", 

        num)

    }

}

func main() {

    ch := make(chan 

    int, 2)

    go producer(ch)

    consumer(ch)

}

计时器

Add(delta int):增加计数器的值。

Done():减少计数器的值。

Wait():阻塞直到计数器为0。

刚才用的例子都是用的sleep来进行操作进行阻塞,这个并不是优雅的,因为我们不知道确切的知道字协程执行的时间,就无法精确的设置sleep的时间。

go语言中其实可以使用WaitGroup,来实现并发任务的一个同步

三个方法

Add(dekta int)计数器+dekta

Done() 计数器-1

Wait() 阻塞直到计数器为0

所以最开始讲协程的例子可以变为

func H(){

var wg sync.WaitGroup

wq.Add(5);

for i:=0 ; i < 5;i++{

go func ( j int){

defer wg,Done()

hello(j)

}(i)

}

wg.Wait()

}

二:依赖管理

GOPATH

1 GOPATH 是一个环境变量

有三个重点

bin ,pkg ,src

2 它的项目代码所有的依赖与src下的代码

3 从go get 下载最新版本的包到src目录下

这样的话会存在一些弊端,无法实现package的多版本控制,

0

因为他们用的时同一个src的源码

GOVander

在项目目录中会添加vendor文件,所有的依赖包都会放到vendor的文件夹中,在引入依赖的副本时优先从vandor里面去寻找,如果找不到再回到GOPATH中。

这样v1找到的是v1版本,v2找到的是v2版本

这样就解决了多个项目需要同一个package依赖的冲突问题

Go Vender的弊端

0

他其实也是依赖的项目的一个源码,并不能很清晰的标识一个版本的概念

Go Module

go module解决了版本等依赖问题

go module首先是用go.mod文件对依赖包版本进行管理(用来配置文件,描述依赖)

然后通过go get/go mod 指令工具来管理依赖包(本地工具)

它的目的是,定义 版本的规则和项目依赖的关系

以来配置

0

version

GOPATH和GOVander都是源码副本的依赖,没有版本的定义

而module有自己的版本规则

语义话版本

#{MAJOR}#{MINOR}#{PATCH}

MAJOR是一个大版本,可以是不兼容的,不同MAJOR间其实是有代码隔离的

MINOR是新增函数和功能,需要在MAJOR下做到前后兼容

PATCH一般是做一些代码bug的修复

例子V1.3.0和V2.3.0

另一个版本规则是基于commit 伪版本

每次提交代码或者提交commit,go都会形成一个伪版本号