线程安全之对象组与对象池
线程池有两个地方可以保证线程安全,1,单线程---一次只能一个线程进入2,线程池中的队列用阻塞队列
。线程池对象多个线程争夺,以这个对象为锁,即实现
对象池:单线程池中的队列中对象,一次只能被一个线程访问
对象组:一个数组装许多单线程池对象,这样数组中的对象本身是线程安全,用时从其队列中获取业务对象(队列中的业务对象不是线程安全的),可以理解为对象组就是多个对象池放入数组
数组就是为了多线程并发,数组中的单线程池对象就是处理多线程并发中同时操作一个对象的问题(放到任务队列等待)---nioeventloop
workers=数组
worker=单线程池对象=nioeventloop,
nioeventloop=selectors+taskqueue
用channel为锁,防止不同线程(客户端,另一个客户端同时操作一个管道)
一个selector一个chanel(selecrors是另起的收集一个管道中所有的该管道注册事件)
boss和worker都是nioEventLoop:
boss---专门用来接收连接建立channels分配给业务处理器worker(hash取模轮回注册给worker中的selector(全局变量)----分配在worker中注册)
workers---对象组
work---单线程池对象---eventLoop(一次一个线程访问) 不断的执行selector监听
selectors(全局变量) + taskqueue
selector监听获取所有channels中可用的 一个channel处理
channel ---所有wokers公用的(worker服务的对象不会固定于某一个channel,哪个向其注册的channel中哪个空闲就用那个)(同步块控制线程安全--channel为门栓)
nio连接的特性: 一个客户端永远是这一个线程(除非关闭连接)+channel门栓---实现只允许一个时刻一个客户端连接操作同一个channel
channel中当前执行的线程中的channel对象和新的任务线程的channel是同一个对象就新的线程不执行放入任务队列,新的线程
进来绑定同一个channel就是另一个客户端(对话的另一端)也企图操作这个channel,这种情况拒绝),同一个线程新的指令没有直接执行不必放入循环队列后续执行(最终都会执行)--这种就实现了一个时刻只允许一个客户端连接操作一个channel
上面是解决io类的冲突,同时通过先把任务执行完,之后检查chanhel的状态,有准备好的channel就io,避免并发冲突(避免io和非io的冲突(渠道的注册之类))
selectors---全局变量
对应上图的概括: