问题提出
当某个对象的接口仅能在单线程(协程)调用时, 所有针对该对象的接口调用都应该处于同一个调度队列中。比如串口的读或者写, 如果多线程读(写)串口,难免出现数据完整性被破坏的问题。为了避免被破坏,就需要在调用接口时加锁保护。更简单一种方法就是将所有对该对象的接口调用都放在同一个调度队列中,这样每一次调用都会按先后顺序执行,不会有任何抢占资源的问题。
实现原理
在传统的编程语言中, 一般的思路是:
- 一个存放任务的队列,一个用于任务队列的资源锁, 一个单独的内部线程
- 内部线程不断的取出队列中的新任务执行
- 设定一个线程退出标志,当标志被设置的时候,内部线程自动结束
Go中的实现原理
- 带资源锁的任务队列可以使用
chan func()
来实现 - 线程可以用
goroutine
来代替 - 退出标志可以是一个简单的
chan bool
队列的数据结构
type DispatchQueue struct {
work chan func() // 任务队列
quit chan bool // 退出标志
Working bool // 运行状态
}
队列实例化
func NewQueue() *DispatchQueue {
q := &DispatchQueue{
work: make(chan func()), quit: make(chan bool)