go中的channel是比条件变量更高阶的同步原语。
一个进程内的资源是共享的,进程内执行体之间的协同包含执行体的互斥,通过互斥锁和读写锁实现,包含执行体之间的同步,同步就是同时进行,通过waitgroup和条件变量实现,还包括执行体之间的通讯,通过channel实现。其实还有一个原子操作,是cpu实现额,和os无关,我看go的锁内部归根是用原子实现的,那么说,锁的本质是原子操作喽。
我认为所谓的执行体之间的互斥啦,同步啦,通信了,归根都是执行体之间的通信,通信都是靠一个公共区,互斥锁,条件变量,wg,channel都是共有变量。
生产者消费者模式是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据。指的是执行体之间同步的问题,生产执行体和消费执行体之间的同步问题。
生产者使用同一套剧本,消费者使用同一套剧本。
假设有10个生产者,10个消费者,一共20个执行体。10个生产者执行同一套针对生产者的剧本,这个剧本只有一个,10个消费者按照同一套消费者剧本去执行,这个消费者剧本也只有一个。还有一个共有的数据块-条件变量,cond,这个变量就一个,而且这个cond里面只有一把锁。这个锁在那套唯一的生产者剧本,和唯一的消费者剧本都出现过。
当存储空间满的时候,生产者发现了,于是执行cond.wait,这个wait内部的实现逻辑是,把自己加入到挂起队列,释放锁,等待被消费者唤醒,如果唤醒就拿锁。
唤醒操作是唤醒的在这个条件变量上挂起的执行体,深入可探索条件变量的实现。
为什么唤醒生产者的只能是消费者执行体呢?我认为,由于锁只有一把,而且锁的是代码,并且无论生产者还是消费者剧本,都是使用的同一把锁,所以,当生产者执行体释放锁,并且挂起自己的时候,锁有可能被另外一个生产者执行体拿走,然后wait,wait之后,除非被唤醒,生产者不再执行,假设所有的生产者都处于wait,那么生产者将无法执行到notify这一过程,所以,能notify生产者执行体的只有消费者执行体了。但是我又有一个疑问???既然锁只有一把,只要剧本被锁,其他执行体也无法执行这个剧本,也就是执行体只有拿到锁才可以读剧本,那要一个生产和消费者不就行了,为啥还要多个生产者和多个消费者呢、?
tip:变量的本质就是数据,函数的本质就是一段操作代码,函数是为了节约反复敲入这段代码,而把这段代码包装起来。
补充:忽然明白了java中的同步原语synchosize锁的是对象的意义,因为java是严格面向对象的,java的synchorize锁的是方法,但是方法是从属于一个对象的,故而锁的是一个对象,对象也就是一块数据。方法从属于这个数据。如果被锁,那么另外一个执行体就无法执行这个对象的方法。也就达到了执行体之间的同步。
而如果锁的是一个函数,也就是这个剧本,那么任何对象都无法使用了就。
代码就是剧本,类,是剧本的剧本。
还有要区分开执行体和对象,执行体是一个cpu上跑着的现成,是独立在cpu上跑的代码,而对象仅仅是一块数据。