go 利用chan的阻塞机制,实现协程的开始、阻塞、返回控制器
一、使用场景
大背景是从kafka 中读取oplog进行增量处理,但是当我想发一条命令将这个增量过程阻塞,然后开始进行一次全量同步之后,在开始继续增量。
所以需要对多个协程进行控制。
二、使用知识
1. 从一个未初始化的管道读会阻塞
2.从一个关闭的管道读不会阻塞
利用两个管道和select 进行控制
三、上代码
控制器代码
package util import (
"errors"
"sync"
) const (
//STOP 停止
STOP = iota
//START 开始
START
//PAUSE 暂停
PAUSE
) //Control 控制器
type Control struct {
ch1 chan struct{}
ch2 chan struct{}
stat int64
lock sync.RWMutex
} var (
//ErrStat 错误状态
ErrStat = errors.New("stat error")
) //NewControl 获得一个新Control
func NewControl() *Control {
return &Control{
ch1: make(chan struct{}),
ch2: nil,
stat: START,
lock: sync.RWMutex{},
}
} //Stop 停止
func (c *Control) Stop() error {
c.lock.Lock()
defer c.lock.Unlock()
if c.stat == START {
c.ch2 = nil
close(c.ch1)
c.stat = STOP
} else if c.stat == PAUSE {
ch2 := c.ch2
c.ch2 = nil
close(c.ch1)
close(ch2)
c.stat = STOP
} else {
return ErrStat
}
return nil
} //Pause 暂停
func (c *Control) Pause() error {
c.lock.Lock()
defer c.lock.Unlock()
if c.stat == START {
c.ch2 = make(chan struct{})
close(c.ch1)
c.stat = PAUSE
} else {
return ErrStat
}
return nil
} //Start 开始
func (c *Control) Start() error {
c.lock.Lock()
defer c.lock.Unlock()
if c.stat == PAUSE {
c.ch1 = make(chan struct{})
close(c.ch2)
c.stat = START
} else {
return ErrStat
}
return nil
} //C 控制管道
func (c *Control) C() <-chan struct{} {
c.lock.RLock()
defer c.lock.RUnlock()
return c.ch1
} //Wait 等待
func (c *Control) Wait() bool {
c.lock.RLock()
ch2 := c.ch2
c.lock.RUnlock()
if ch2 == nil { //通过赋值nil 发送停止推出命令
return false
}
<-ch2 //会进行阻塞
return true
}
使用代码
for {
select {
case part, ok := <-c.Partitions():
if !ok {
conf.Logger.Error("get kafka Partitions not ok", regular.Name)
return
}
go readFromPart(c, part, regular, respChan)
case <-regular.C(): //regular 为Control 类
if !regular.Wait() {
conf.Logger.Debug("Stop! ")
return
}
conf.Logger.Debug("Start! ")
}
}
这样就可以随时随地的控制工程中的协程
regular := util.NewControl()
regular.Pause()
regular.Start()
regular.Stop()
go 利用chan的阻塞机制,实现协程的开始、阻塞、返回控制器的更多相关文章
- golang协程——通道channel阻塞
新的一年开始了,不管今天以前发生了什么,向前看,就够了. 说到channel,就一定要说一说线程了.任何实际项目,无论大小,并发是必然存在的.并发的存在,就涉及到线程通信.在当下的开发语言中,线程通讯 ...
- qemu核心机制分析-协程coroutine
关于协程coroutine前面的文章已经介绍过了,本文总结对qemu中coroutine机制的分析,qemu 协程coroutine基于:setcontext函数族以及函数间跳转函数siglongjm ...
- Python并发编程系列之常用概念剖析:并行 串行 并发 同步 异步 阻塞 非阻塞 进程 线程 协程
1 引言 并发.并行.串行.同步.异步.阻塞.非阻塞.进程.线程.协程是并发编程中的常见概念,相似却也有却不尽相同,令人头痛,这一篇博文中我们来区分一下这些概念. 2 并发与并行 在解释并发与并行之前 ...
- Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就绪,挂起,运行) ,***协程概念,yield模拟并发(有缺陷),Greenlet模块(手动切换),Gevent(协程并发)
Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就 ...
- python--基础知识点梳理(三)深浅拷贝、进线协程、os和sys、垃圾回收机制、读文件的三种方式
深拷贝与浅拷贝 import copy 浅拷贝:将一个对象的引用拷贝到另一个对象上,所以如果我们在拷贝中改动,会影响到原对象.copy.copy() 深拷贝:将一个对象拷贝到另一个对象中,新开辟了一个 ...
- Openresty Lua协程调度机制
写在前面 OpenResty(后面简称:OR)是一个基于Nginx和Lua的高性能Web平台,它内部集成大量的Lua API以及第三方模块,可以利用它快速搭建支持高并发.极具动态性和扩展性的Web应用 ...
- PHP 协程:Go + Chan + Defer
Swoole4为PHP语言提供了强大的CSP协程编程模式.底层提供了3个关键词,可以方便地实现各类功能. Swoole4提供的PHP协程语法借鉴自Golang,在此向GO开发组致敬 PHP+Swool ...
- Python3的原生协程(Async/Await)和Tornado异步非阻塞
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_113 我们知道在程序在执行 IO 密集型任务的时候,程序会因为等待 IO 而阻塞,而协程作为一种用户态的轻量级线程,可以帮我们解决 ...
- 基于ASIO的协程库orchid简介
什么是orchid? orchid是一个构建于boost库基础上的C++库,类似于python下的gevent/eventlet,为用户提供基于协程的并发模型. 什么是协程: 协程,即协作式程序,其思 ...
- python之协程与IO操作
协程 协程,又称微线程,纤程.英文名Coroutine. 协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B ...
随机推荐
- 20191010-7 alpha week 1/2 Scrum立会报告+燃尽图 05
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/8750 一.小组情况 队名:扛把子 组长:迟俊文 组员:宋晓丽 梁梦瑶 韩 ...
- Scrapy持久化存储-爬取数据转义
Scrapy持久化存储 爬虫爬取数据转义问题 使用这种格式,会自动帮我们转义 'insert into wen values(%s,%s)',(item['title'],item['content' ...
- 《Windows内核安全与驱动开发》 2.3 重要的数据结构
<Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 2.3 重要的数据结构 一.驱动对象 Windows内核采用__的编程方式 ...
- mysql 替换 tab 键 (\t)
update t_instance set instance_name = replace(instance_name,'\t','') , host_name = replace(host_name ...
- 程序员修神之路--打通Docker镜像发布容器运行流程
菜菜哥,我看了一下docker相关的内容,但是还是有点迷糊 还有哪不明白呢? 如果我想用docker实现所谓的云原生,我的项目该怎么发布呢? 这还是要详细介绍一下docker了 Docker 是一个开 ...
- docker镜像、docker容器导入导出命令
一.docker镜像导入导出命令 导出命令: docker save -o <保存路径> <镜像名称:标签> docker save -o ./test.tar test:la ...
- 转:Maven的默认中央仓库以及修改默认仓库&配置第三方jar包从私服下载
当构建一个Maven项目时,首先检查pom.xml文件以确定依赖包的下载位置,执行顺序如下: 1.从本地资源库中查找并获得依赖包,如果没有,执行第2步. 2.从Maven默认中央仓库中查找并获得依赖包 ...
- MySql数据库之单表数据查询
查询数据 1.查询所有数据: select * from 表名; 2.根据指定条件查询数据:
- sass 安装过程中的坑
1,需要在项目中使用sass/scss 功能需要先在项目中安装,安装方法: cnpm install node-sass --save-dev //安装node-sass cnpm install s ...
- 数据库Oracle 数字,字符,日期之间的相互转换
数据类型转换分为俩种 . 隐式数据类型转换:当源数据的类型和目标数据的类型不同的时候,如果没有转换函数,就会发生隐式转换,也称自动转换. 对于直接赋值转换: 对于表达式赋值: 隐式转换的问题: 性能 ...