java synchronized原理

临界区

对共享资源读写的代码块,如synchronized内的代码

竞态条件

多线程访问共享资源而导致结果不同,则称为发生了竞态条件、

Monitor原理

Monitor 被翻译为监视器或管程
1、对象头:正常对象头为64bit(位)8个字节,markword占32bit,klassword为对象指针占32bit
2、数组对象头为96bit,另外32bit为array length所有
3、正常markword中包含25bit hashcode码,age分代年龄4bit,biased_lock 偏向锁1bit,01 加锁状态2bit
4、当线程加锁后,线程的对象头会对应一个monitor对象,markword中30bit形成指针指向monitor,另外两位为锁类型
5、monitor中维护的属性有:
	owner,表示当先锁的拥有者,为current thread
	entry_list,表示存放的别的阻塞的线程
	wait_set,线程调用wait方法进入waiting状态,进入wait_set中阻塞,当有别的线程调用notify方法时进行

Synchronized原理

1、线程通过常量池中的ACC_SYNCHRONIZED标志来判断是否使用同步
2、如果同步,则用monitor来控制锁的拥有,如果占有对象,则将monitor中的owner属性指向当前线程。
3、通过monitorenter字节码指令进入同步代码,通过monitorexit字节码指令来退出同步块。
4、当线程未加锁或者被当前线程所有,则使monitor中的计数器+1。释放锁时,则使计数器-1.当计数为0时,线程就彻底释放该锁了。如果获得锁失败,则线程进入阻塞状态。直到别的线程释放锁。
5、monitor本质通过操作系统的Mutex Lock(互斥锁)来实现加锁。线程之间的转换效率较低,因此synchronized叫重量级锁。

jvm对synchronized的优化

1、偏向锁:
	jdk1.6后默认开启偏向锁和轻量级锁 ,可以设置参数关闭。
	当同一个线程多次加锁时开动
	锁偏向:当线程执行加锁操作时,发现owner是自己,则无需进行cas加锁操作。计数加1,此时发生锁偏向,biased_lock 由0变为1,锁标志位为00
	批量撤销:当撤销偏向锁阈值达到40次时,jvm会设置撤销整个类的所有偏向锁,新建的锁对象也不能加偏向锁。
	批量重偏向:当重偏向阈值达到20时,jvm会将类中的所有对象进行批量重偏向。
2、轻量级锁:
	线程中创建lock record锁记录对象,用来存储锁定对象的mark word。加锁时尝试用cas替换锁定对象object的mark word 存放lock record地址和状态00。如果替换成功,则加锁成功。
	当多个线程交替执行,并没有发生锁竞争时,加轻量级锁
	锁膨胀:当轻量级锁cas加锁仍失败时,线程会为加锁对象申请monitor锁。让object指向monitor地址。
	然后让自己阻塞。在持有锁的对象解锁时,这是cas将markword 的值还给加锁对象object的对象头。这时会失败。只能按照重量级锁的解锁流程来解锁。即找到monitor地址,找到monitor对象,将owner置为null。并唤醒entrylist中的blocked线程。
3、重量级锁:	
	当轻量级锁发生竞争失败时,轻量级锁发生锁膨胀升级为重量级锁
	自旋优化:重量级锁在加锁失败时,会cas自旋优化,适合多核cpu时,自适应自旋是指成功后,下次会多自旋几次,失败了则下次少执行几次。减少上下文转换。避免阻塞。
4、锁粗化:将多个临界区合并为一个
5、锁消除:当发现锁保护的数据操作不会发生分享,并不回从该方法中逃逸。jvm会消除锁。jvm可以设置这个开关。-XX:-EliminateLocks

synchronized用法

1、加在成员方法上
2、加在静态方法上 = 加在类对象上
3、加在方法代码块
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值