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 ...
随机推荐
- ProxySQL读写分离代理
实现ProxySQL反向代理Mysql读写分离 简介 ProxySQL相当于小型的数据库,在磁盘上有存放数据库的目录:ProxySQL用法和mysql相似 启动ProxySQL后会有两个监听端口: 6 ...
- 【Linux系列】Centos 7安装 PHP(四)
目的 为了下面的Laravel部署,本篇开始安装PHP. 设置PHP源 查看Centos源是否有PHP. yum list php* 进一步查看PHP的版本. yum info php.x86_64 ...
- 【Luogu P3387】缩点模板(强连通分量Tarjan&拓扑排序)
Luogu P3387 强连通分量的定义如下: 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶 ...
- 内核升级在线安装报错:Could not retrieve mirrorlist http://mirrors.elrepo.org/mirrors-elrepo-kernel.el7 error was14: curl#6 - "Could not resolve host: mirrors.elrepo.org; 未知的错误"
修改网卡配置 [root@localhost ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens32 BOOTPROTO="none" ...
- Spring IOC初始化深度解析
1.前言 本文是基于JAVA配置方法对Spring IOC进行分析,掌握Spring IOC初始化流程对于我们更好的使用Spring.学习Spring还是很有帮助的,本文所使用的的Spring版本为5 ...
- day20190915write from memory
jQuery_Chapter02_20190912/ jQuery操作类样式.html <!DOCTYPE html> <html> <head> <meta ...
- javaScript中的indexOf使用方法
JavaScript中的indexOf使用方法 概述 indexOf大小写敏感,其中的O要大写 对于字符串而言 indexOf返回字符串第一次出现的位置,若没有出现返回-1 1 var str = & ...
- div水平垂直居中的六种方法
在平时,我们经常会碰到让一个div框针对某个模块上下左右都居中(水平垂直居中),其实针对这种情况,我们有多种方法实现. 方法一: 绝对定位方法:不确定当前div的宽度和高度,采用 transform: ...
- (Nginx+PHP+MySQL)单机+Redis部署
链接:Nginx+PHP+MySQL+Redis多机部署 1.lnmp+redis工作机制 2.lnmp+redis操作步骤(lnmp为单机部署) (1)lnmp+redis实战环境 lnmp服务器: ...
- mongoDB学习笔记(一)之操作符
本文主要讲解mongoDb的一些常用的操作符的用法.随着作者本身的能力的提高,本文也会不断的完善. 官方文档链接为有: https://docs.mongodb.com/manual/referenc ...