协程

弄懂goroutine调度原理

随声附和 提交于 2019-11-29 10:19:01
goroutine简介 golang语言作者Rob Pike说, “Goroutine是一个与其他goroutines 并发运行在同一地址空间的Go函数或方法。一个运行的程序由一个或更多个goroutine组成。它与线程、协程、进程等不同。它是一个goroutine“ 。 goroutine通过通道来通信,而协程通过让出和恢复操作来通信; goroutine 通过Golang 的调度器进行调度,而协程通过程序本身调度; 简单的说就是Golang自己实现了协程并叫做goruntine(本文称Go协程),且比协程更强大。 goroutine调度原理 上面说到Go协程是通过Golang的调度器进行调度的,其中调度器的线程模型为两级线程模型。 有关两级线程模型的介绍,可以看 这篇文章 我们来看下Golang实现的两级线程模型是怎样的。首先要知道这三个字母代表的含义 M :代表内核级的线程 P :全程Processor,代表运行Go协程所需要的资源(上下文环境) G :代表Go协程 我们先看下为实现调度Golang定义了这些数据结构存M,P,G 名称 作用范围 描述 全局M列表 Go的运行时 存放所有M的单向链表 全局P列表 Go的运行时 存放所有P的数组 全局G列表 Go的运行时 存放所有G的切片 调度器的空闲M列表 调度器 存放空闲M的单向链表 调度器的空闲P列表 调度器

srs3.x代码阅读

随声附和 提交于 2019-11-29 08:25:30
srs使用了state-threads协程库,是单线程多协程模型。不用考虑线程安全,数据不用加锁。 int SrsServer::listen()中启动if ((ret = listen_rtmp()) != ERROR_SUCCESS) 进一步启动:SrsListener* listener = new SrsBufferListener(this, SrsListenerRtmpStream); 然后启动: SrsTcpListener::SrsTcpListener(ISrsTcpHandler* h, string i, int p) { handler = h; ip = i; port = p; lfd = NULL; trd = new SrsDummyCoroutine(); } 在协程的cycle中,会调用到if ((ret = handler->on_tcp_client(client_stfd)) != ERROR_SUCCESS) 在on_tcp_client()中,会调用if ((ret = server->accept_client(type, stfd)) != ERROR_SUCCESS) int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)

Go的sync.Cond(四)

天涯浪子 提交于 2019-11-29 06:23:01
Cond cond其实就是哪个控制协程执行的包函数:让哪个执行,让全部执行,给函数标注,让函数等待执行,给函数加锁解锁 Signal是执行一个协程的信号 Broadcast是执行全部协程的信号 wait 协程等待通知,阻塞在此 NewCond创建条件 cond.L.Lock() 给协程加锁 cond.L.Unlock() 释放锁 package main import ( "fmt" "sync" "time" ) var locker = new(sync.Mutex) var cond = sync.NewCond(locker) var waitgroup sync.WaitGroup func test(x int) { //获取锁 cond.L.Lock() //等待通知,阻塞在此 // func (c *Cond) Wait():挂起goroutine的操作 cond.Wait() fmt.Println(x) time.Sleep(time.Second * 1) defer func() { cond.L.Unlock() //释放锁 waitgroup.Done() //减一个协程 }() } // cond其实就是哪个控制协程执行的包函数 // Signal是执行一个协程的信号 // Broadcast是执行全部协程的信号 // wait 协程等待通知,阻塞在此

Go的sync.Mutex(七)

佐手、 提交于 2019-11-29 06:22:49
原文 https://www.cnblogs.com/shockerli/p/golang-pkg-mutex.html 简介 多个协程会操作一个特定资源,就会出现意想不到的错误,所以我们使用互斥锁, 一个协程使用特定资源的时候进行锁定,用完解锁, 再让其他协程使用,所以其他协程想使用此资源,必须自己给资源解锁或等待正在使用的协程解锁 在代码中就是锁定一段代码,代码里面有资源。 注意 在一个 goroutine 获得 Mutex 后,其他 goroutine 只能等到这个 goroutine 释放该 Mutex 使用 Lock() 加锁后,不能再继续对其加锁,直到利用 Unlock() 解锁后才能再加锁 在 Lock() 之前使用 Unlock() 会导致 panic 异常 已经锁定的 Mutex 并不与特定的 goroutine 相关联,这样可以利用一个 goroutine 对其加锁,再利用其他 goroutine 对其解锁 在同一个 goroutine 中的 Mutex 解锁之前再次进行加锁,会导致死锁 适用于读写不确定,并且只有一个读或者写的场景 代码 package main import ( "fmt" "sync" "time" ) func ccc(i int)(){ mutex.Lock() fmt.Println("Lock:", i) time.Sleep

并发编程:进程+线程+协程

三世轮回 提交于 2019-11-29 05:56:16
现代计算机系统是由一个或者多个处理器,主存,磁盘,打印机,键盘,鼠标显示器,网络接口以及各种其他输入 输出设备组成的复杂系统,每位程序员不可能掌握所有系统实现的细节,并且管理优化这些部件是一件挑战性极强 的工作。所以,我们需要为计算机安装一层软件,成为操作系统,任务就是用户程序提供一个简单清晰的计算机模 型,并管理以上所有设备。 定义也就有了:操作系统是一个用来协调、管理和控制计算机硬件和软件资源的系统程序,它位于硬件和应用程序之间。 (程序是运行在系统上的具有某种功能的软件,比如说浏览器,音乐播放器等。) 操作系统的内核的定义:操作系统的内核是一个管理和控制程序,负责管理计算机的所有物理资源,其中包括:文件系 统、内存管理、设备管理和进程管理。 过程: 万能程序员们将对应于程序和数据的已穿孔的纸带(或卡片)装入输入机,然后启动输入机把程序和数据输入计算机 内存,接着通过控制台开关启动程序针对数据运行;计算完毕,打印机输出计算结果;用户取走结果并卸下纸带(或 卡片)后,才让下一个用户上机。 注意点: 程序员需要在墙上的计时表上预约时间 同一时刻只有一个程序在内存中被CPU调用运行(串行的) 优缺点: 优点:程序员在申请的时间段内独享整个资源,即时的调试自己的程序,如果有bug可以当场处理, 缺点:这对于计算机提供商来说是一种浪费(你买一台电脑4000块,那

python3.6异步IO包asyncio部分核心源码思路梳理

情到浓时终转凉″ 提交于 2019-11-29 03:41:20
关于python异步编程的演进过程,两篇文章阐述得妥妥当当,明明白白。 中文资料:https://mp.weixin.qq.com/s?__biz=MzIxMjY5NTE0MA==&mid=2247483720&idx=1&sn=f016c06ddd17765fd50b705fed64429c 英文资料:http://aosabook.org/en/500L/a-web-crawler-with-asyncio-coroutines.html 其实中文资料就是参考的英文资料,英文资料是开源书《 500 Lines or Less 》中的一个主题章节,整书地址:https://github.com/aosabook/500lines python的asyncio源码的核心思路其实跟基于生成器的协程异步编程思路大体一致,只是前者做了大量的代码优化和功能扩充。所以对照生成器协程代码来理解asyncio是很有帮助的。以下的这一小段代码就是采用基于生成器的协程的异步编程方式写的一个小爬虫案例,来自上述中文资料,asyncio的核心代码的思路大体上能从这段代码中找到原型。 该脚本命名为:yield_from.py import socket from selectors import DefaultSelector, EVENT_READ, EVENT_WRITE selector =

php 协程理解

末鹿安然 提交于 2019-11-29 01:42:53
生成器 生成器最基本的思想也是一个函数,这个函数的返回值是依次输出,而不是只返回一个单独的值。或者,换句话说,生成器使你更方便的实现了迭代器接口。下面通过实现一个xrange函数来简单说明: <?php function xrange($start, $end, $step = 1) { for ($i = $start; $i <= $end; $i += $step) { yield $i; } } foreach (xrange(1, 1000000) as $num) { echo $num, "\n"; } 生成器为可中断的函数 要从生成器认识协同程序,理解它们内部是如何工作的非常重要:生成器是可中断的函数,在它里面,yield构成了中断点。 协程 协程给上面功能添加的主要东西是回送数据给生成器的能力。这将把生成器到调用者的单向通信转变为两者之间的双向通信。 用send 将数据给函数 <?php function gen() { $ret = (yield 'yield1'); var_dump($ret); $ret = (yield 'yield2'); var_dump($ret); } $gen = gen(); var_dump($gen->current()); // string(6) "yield1" var_dump($gen->send('ret1')

unity的yield

元气小坏坏 提交于 2019-11-29 00:23:14
这里说的是Unity通过StartCoroutine开启IEnumerator协程里的yield相关 1.yield return 0,yield return null 等待下一帧接着执行下面的内容 2.yield return new WaitForSeconds(float secs) 等待指定秒数,接着执行下面的内容 3.yield return www; 使用www下载,等待下载完成后再执行下面代码 4.yield return StartCoroutine("协程方法名") 先执行协程方法,并等待,直到该协程方法执行完再执行后面的内容 5.yield break 退出协程,不执行break后面的代码 6.yield return resourcesRequest; 异步取到文件后执行后面的代码 来源: https://www.cnblogs.com/mcyushao/p/11434997.html

python3 协程

半世苍凉 提交于 2019-11-29 00:19:01
协程,又称为'微线程'。英文名Coroutine。 协程的特点:一个线程执行 协程的优势: 1、执行效率高 因为协程切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。 2、不需要多线程的锁机制 因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。 因为协程是一个线程执行,那怎么利用多核CPU呢?最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。 来源: https://www.cnblogs.com/AndyChen2015/p/11434530.html

python多线程、多进程、协程笔记

倖福魔咒の 提交于 2019-11-28 23:57:57
import threading import time import multiprocessing import asyncio movie_list = ['斗破.avi', '复仇者联盟.mp4', '斗罗大陆.rmvb'] music_list = ['七里香.mp3', '美人鱼.mp3', 'xxx.obi'] movie_format = ['avi', 'mp4', 'rmvb'] music_format = ['mp3'] def play(playlist): for i in playlist: if i.split('.')[1] in movie_format: print('您现在正在收看:{}'.format(i)) time.sleep(2) elif i.split('.')[1] in music_format: print('您现在正在收听:{}'.format(i)) time.sleep(2) else: print('该文件格式不支持:{}'.format(i)) time.sleep(2) async def async_play(playlist): for i in playlist: if i.split('.')[1] in movie_format: print('您现在正在收看:{}'.format(i)) await