内核线程有2种
一是指内核使用的线程,一般不固定绑定用户空间,服务哪个就绑定哪个,甚至根本没用户空间;
另外就是跟用户态线程对应的,是指有内核管理的线程。
用户态线程就是应用程序自己管理的线程,内核看不到;
就像房间,操作系统可以看到一个个房间,但是看不到房间里面的一个个人;
房间里面的人可以做用户态线程。
线程的用户态跟内核态是指同一个线程上下文,不同的代码执行:
用户态就是应用程序的代码;
内核态就是内核代码,设备驱动代码,这些内核态代码运行在线程的上下文里面,
比如中断,系统调用,就会把执行权交给内核态代码。
摘自 https://www.zhihu.com/question/316816087/answer/630015850
1、synchronized
synchronized关键字需要一个引用类型的参数,这个参数也叫做监听器(monitor);JVM通过这个监听器来管理所有需要同步的线程(synchronized这个监听器的所有线程)运行状态,成功占有该monitor的线程即成为该监听器的owner,其他线程则被状态切换至阻塞状态并维护在一个队列中准备下一次的竞争;
线程状态可用下图表明:
------------------------------------------------ pic -------------------------------------------------------------------
------------------------------------------------ pic -------------------------------------------------------------------
大家知道线程在不同状态之间切换是比较消耗cpu资源的,所以使用synchronized处理较大并发的场景性能开销是比较大的;
(大致可以这样理解,如果有兴趣可以查看反编译带有synchronized的class文件,内在实现还是挺复杂的)
2、ReentrantLock
以非公平锁为例
多个线程调用同一个ReentrantLock对象的lock()方法时,大致原理是每个线程都尝试去修改锁对象内一个状态属性state(继承自java.util.concurrent.locks.AbstractQueuedSynchronizer)的值,这个修改过程采用了CAS(compare and swap)技术即每个线程都想把这个变量从数值0改变成1;
如果一个线程修改成功则成功锁对象的owner,否则LockSupport.park中止该线程,并调用改线程的interrupt方法设置线程的interrupted状态,并创建一个node存放该线程并将node加入链表中;
当某线程a调用unlock方法时,从链表中取出a线程对应node的next节点并调用LockSupport.unpark给对应线程一个许可让其继续执行;