Goroutine是GO语言的奇特并发主体。这是一个由go关键字启动的轻质线程。在真正的GO语言实现中,Goroutine和System线程不等。尽管两者之间的差异实际上只是差异,但这种定量更改导致了GO语言首先要跳跃。每个系统级线程将具有固定的大小堆栈(通常默认值为2MB)。此堆栈主要用于保存参数和本地变量时,当递归调用该功能时。固定堆栈的大小导致两个问题:一个是仅需要一个小堆栈空间的许多线程的巨大浪费。问题是:要么降低固定的堆栈尺寸并增加空间的利用;或增加堆栈的大小以允许更深的功能递归地调用,但是两者不能同时可用。相反,Goroutine将从小堆栈开始(可能是2KB或4KB)。当深递归引起当前的堆栈空间时,Goroutine会动态解释堆栈的大小(在堆栈的主流实现中,主流堆栈的最大值的最大值达到1GB)。因为价格很小,我们可以轻松地轻松启动数千个goroutine.go还包含自己的调度程序。该调度程序使用一些技术手段在N操作系统线程上安排Moroutine。GO Scheduler的工作类似于内核的计划,但是该调度程序仅在单个GO程序中注意Goroutine。-semi-占地协作计划。只有当当前的goroutine发生时,调度才能发生;同时, 调度程序只能根据特定函数保存必要的寄存器。man..man.there.gomaxprocs在运行时变量,以控制运行正常非屏蔽goroutine的系统线程的数量,然后执行main函数。代码在同一goroutine中运行,这是程序的主要系统线程。因此,如果在init函数中使用GO关键字激活新的Goroutine,则只有在输入Main.Main函数后才能执行新的Goroutine。
SO值的原子操作是并发编程中的“最小和无关紧要的”操作。通常,如果多个并发物体在同一共享资源上的操作是原子,那么同时,只有一个并发物体可以运行资源。从线程的角度来看,在当前线程修改和共享资源期间,其他线程无法访问资源。原子操作与多线程并发编程模型的单线线程事故没有什么不同,可以保证共享资源的完整性。正常情况下,原子操作是通过“相互访问”来保证的,通常会受到特殊CPU指令的保护。
在工人周期中,为了确保总数的原子性。值 += i,我们只能通过sync.mutex lock and Unlock。在进入和退出关键区域之前和退出关键区域是必要的。如果没有锁定保护,则由于多线程之间的竞争,总数的最终值可能是不正确的。使用相互锁来保护数值共享资源,该资源是麻烦且效率低下。标准库的同步/原子包为原子操作提供了丰富的支持。我们可以重新实现上述示例:
Atomic.AdDuint64函数调用可以确保Total的阅读,更新和保存是一种原子操作,因此在多线程中访问也是安全的。原子操作可以实现非常有效的单个模式。相互锁定的成本远高于该模式。普通整数的原子。在性能敏感的地方,可以添加数字徽标。通过原子检测徽标状态相互锁定的使用数量可以提高性能。
基于同步实现单模式
同步/原子软件包为基本数值类型和复杂对象的原子操作提供了支持。原子原子对象提供两种原子方法:加载和存储,用于加载和保存数据。返回值和参数是接口{}类型,因此可以用于任何自定义复杂类型。
通道通信是Goroutine之间同步的主要方法。不满意的通道上的EAVEN发送操作与其相应的接收操作配对。发送和接收操作通常发生在不同的goroutine上(在同一goroutine上执行两个操作可以很容易地导致死锁)。无与伦比的通道上的发送操作总是在相应的接收操作之前发生。
尽管该程序在Goroutine和Main之间没有严格的关系,因为收到完成频道的返回需要发生,但这可以确保主线程不会在执行之前不会结束。它可以保证打印“您好,世界”。该程序首先写入MSG,然后在完成管道上发送同步信号,然后从完成的DONE接收相应的同步信号,最后执行println函数。如果在关闭频道后继续进行数据,则接收器将接收到接收器因此,在此示例中,使用关闭(c)关闭管道而不是完成<-false仍然可以确保程序产生相同的行为。将引起计划的恐慌。建议不要在这里关闭它。频道还可以实现不同的goroutine处理。对于带缓冲区的通道,对于通道的第一个k的k+c的k+c的完成操作已完成,其中c是通道的高速缓存。如果C集C到0,它自然地对应于没有缓存的缓存。由于不令人满意的通道只能发送一个同步,它可以简化为没有缓存的规则:从no Buffer频道完成频道之前发生的接收。我们可以控制。我们可以控制通道的高速缓存大小控制执行的goroutine数量的最大数量:
在周期中创建Goroutine的过程中,使用了匿名函数,并在该函数中引用了周期变量W。由于w是引用和传输而不是传输的,因此不能保证W.一个值,为了解决此问题,我们可以使用函数的值来传递该函数的值,以复制每个功能的端口Goroutine。可以同时同时分别打印相同的。
有一种简单的方法可以等待下一步操作等待N线程完成下一步。
介质WG.ADD(1)用于增加等待事件的数量,并且必须在背景线程启动之前确保执行该数量(如果将其放置在后台线程中以进行执行,则不能保证它正常执行))当背景线程完成后,请致电wg.done()指示事件已完成。主函数的wg.wait()正在等待所有事件。创建周期后,最后一个句子选择{}在主要功能中是一个空管道选择语句。此语句将导致主线程阻止,从而避免了程序的过早出口。也有许多方法,例如{},<-make(chan int)和其他可以实现相似效果的方法。被阻止,如果需要正常退出程序,则可以通过调用OS.EXIT(0)来实现。
并发编程的最常见示例是生产者消费者模型。该模型主要通过生产和消费能力来改善程序的总体处理数据。简而言之,它是生成数据,然后将其放入结果队列中。消费者从结果的结果中获取数据,以便在队列中获取数据,因此,一件事要拆卸并分解为前条件的产生和后方消耗的异步行为。当结果队列中没有数据时,消费者进入等待饥饿;当结果队列中的数据已满时,生产商正面临着由于产品压缩而剥夺了CPU的问题。
我们已经打开了2种产品来生产流线,这些产品用于生成3和5序列。然后打开消费者消费者线程以打印获得的结果。我们可以使主函数在没有退出的情况下保存阻止状态。只有当用户输入CTRL-C时,该程序才能真正退出程序。我们的示例中有2个生产者,两个生产者之间没有同步事件。消费者仍然可以彼此合作。
观察者模式也可以称为释放模式,定义对象之间的一对依赖关系,并且在需要多个对象更改对象时需要相应的响应。对于观察者,他不在乎谁观察自己,只能出版自己变化。这也是观察者的好处。使用注册以增加或减少观察者,但对观察者没有影响。
有关特定实施,请参阅以下内容:
此方法将容纳对象。在许多情况下,无需持有对象。您可以将函数用作要调用的参数输入。更新被称为该函数的调用函数。当数据更改时,调用呼叫。更复杂的是通知此问题作为生产的内容,该调用被用作消费者手段实现异步调用,并且可以实现异步调用:
如此简单的转换可以使观察者模型更有用。在同一时间,重要的是要注意许多MVVM模式可以说是这种观察模式,例如VUE和依赖的MVVM模式,这些模式刷新了界面。(但是个人个人。,MVVM的困难在于构建数据劫持和类似树的依赖性,而不是观察者模式)