synchronized
synchronized是一种互斥锁,一次只能允许一个线程进入被锁住的代码块;
是Java的一个关键字,它能将代码块或者方法锁起来;
它的锁级别是对象级别:修饰实列方法时,锁的对象是调用方法的实列;修饰的方法是静态方法时,锁的对象是当前类的Class实例;修饰的是代码块时,锁的是传入synchronized传入的对象实例;
在内存中,对象一般由三部分组成,分别是对象头、对象实例数据、对齐填充;在对象头里有个mark work信息会记录对象锁的信息,还有每个对象都会有一个monitor 对象,monitor对象中存储着当前持有锁的线程以及等待锁的队列;
在jdk1.6之前synchronized是重量级锁,在线程进入同步方法\代码块时,monitor对象会存储当前线程的id,然后将monitor对象的地址保存在对象头的mark work里,加锁是依赖底层操作系统的mutex相关的指令,所以会存在用户态和内存态的转换,性能消耗十分明显;而jdk1.6以后引入了偏向锁和轻量级锁在JVM层面实现加锁的逻辑,不依赖底层操作系统底,就没有切换的消耗;
加锁过程:
线程请求持有锁,当对象没有线程持有锁时,在mark work直接记录线程id,只要线程来执行同步代码,就会比较线程id是否相等,相等则当前线程持有锁,执行同步代码;如果不相等,则利用CAS来尝试修改当前线程id,如果CAS修改成功,那持有锁,执行同步代码;如果失败,说明有竞争环境,此时会对偏向锁撤销,升级为轻量级锁;轻量级锁状态下,当前线程会在栈帧下创建锁记录(Lock Record),将Mark work的信息复制到锁记录里,且有个Owner指针指向加锁对象;当有线程执行到同步代码时,则利用CAS试图将Mark work的指向到线程栈帧的锁记录,如果修改成功,则获取到轻量级锁,失败则自旋,自旋一定次数后,则升级为重量级锁。