1.synchronized:通过对象锁和操作系统得锁(互斥量mutex),来实现同步
原理:1.向操作系统申请锁(互斥量mutex),涉及到内核态和用户态得切换
2.改变对象头的锁标志位,表明对象的锁是否被占有,线程保存对象头的信息,对象头保存指向锁对象的指针
有锁争用时,未获得的锁得线程会被阻塞,当锁释放时,系统唤醒被阻塞的线程
关于操作系统阻塞和唤醒线程:原理类似于java的aqs
阻塞和唤醒线程需要操作系统执行内核代码,所以有内核态和用户态的切换
用户态:执行用户代码
内核态:执行内核代码
阻塞的动作涉及到线程切换
关于线程切换:
线程切换时,需要把正在执行的线程的所有信息(cpu各个寄存器的数据)保存到TBC块,把要执行的线程的TBC块里的信息加载到cpu
2.由于线程争用时有阻塞,唤醒动作,消耗资源所以,java1.6之后优化了synchronized
1)自旋锁:如果锁得占用时间很短,阻塞,唤醒线程很耗时,所以有了自旋锁:不阻塞,停一下又去争用锁,自选一定次数,进入阻塞
2)自适应自旋锁:自旋多少次很难确定,所有有了自适应自旋锁,根据之前的自旋次数改变本次得自旋次数
3)轻量级锁:1中得锁被称为重量级锁,因为涉及到操作系统的锁,会进行内核态和用户态得切换,比较耗资源
轻量级锁只获取对象的锁,并不向操作系统申请锁,但也无法阻塞争用的线程,所以适合没有争用的场景,避免了反复向操作系统申请和释放锁
每次申请和释放锁,只改变对象头
4)偏向锁:如果没有线程争用,一个线程反复申请释放轻量级锁则要反复改变对象头,偏向锁适合这种场景
偏向锁在第一次获取锁后,不释放锁,避免了反复改变对象头,当发生锁争用,则升级为轻量级锁