【J.U.C详解】--深入理解synchronized

目录

  1. synchronized使用
  2. synchronized实现原理
  3. synchronized优化

一、synchronized使用

在JDK1.5的时候,synchronized被称作为重量级锁。他的效率远不如Lock。但是在JDK1.6的时候,sun对其做了很多优化,因此效率不在是一个考虑指标了,synchronized也是在那么重了。

synchronized可以修饰方法和作用于同步代码块两个地方,当修饰静态方法的时候,锁的是当前静态类,作用于实例方法上,锁的是当前实例对象。作用于同步代码块的时候,锁的是括号里面的对象,代码示例:

public class A{

	//①锁的是当前类对象 class
	public static synchronized void test1(){
		//doto
	}

	//②锁的是当前实例对象
	public synchronized void test2(){
		//doto
	}

	//③锁的是括号里面的对象
	public void test3(){
		synchronized (object){
			//todo
		}
	}
}

二、synchronized实现原理

1)同步代码块是使用 monitorenter 和 monitorexit 指令实现的;
2)同步方法(在这看不出来需要看JVM底层实现)依靠的是方法修饰符上的ACC_SYNCHRONIZED 实现。

任何对象都有一个 Monitor 与之相关联,当且一个 Monitor 被持有之后,他将处于锁定状态。

三、锁优化

在JDK1.6的时候,sun对synchrornized做了很多优化,使其性能得到了极大的提升。其中有自旋锁、锁消除、锁粗化、偏向锁和轻量级锁等

  • 1.自旋锁
    线程的阻塞和唤醒,需要 CPU 从用户态转为核心态。频繁的阻塞和唤醒对 CPU 来说是一件负担很重的工作,势必会给系统的并发性能带来很大的压力。同时,我们发现在许多应用上面,对象锁的锁状态只会持续很短一段时间。为了这一段很短的时间,频繁地阻塞和唤醒线程是非常不值得的。所以引入自旋锁。所谓自旋锁,就是让该线程等待一段时间,不会被立即挂起,看持有锁的线程是否会很快释放锁。

  • 2 锁消除
    为了保证数据的完整性,我们在进行操作时需要对这部分操作进行同步控制。但是,在有些情况下,JVM检测到不可能存在共享数据竞争,这是JVM会对这些同步锁进行锁消除。如果不存在竞争,为什么还需要加锁呢?所以锁消除可以节省毫无意义的请求锁的时间。

  • 3.锁粗化
    我们知道在使用同步锁的时候,需要让同步块的作用范围尽可能小:仅在共享数据的实际作用域中才进行同步。这样做的目的,是为了使需要同步的操作数量尽可能缩小,如果存在锁竞争,那么等待锁的线程也能尽快拿到锁。在大多数的情况下,上述观点是正确的。但是如果一系列的连续加锁解锁操作,可能会导致不必要的性能损耗,所以引入锁粗话的概念。

  • 4.偏向锁
    通过观察,大多数情况下,同一个锁总是被一个线程持有,那么就记录下这个线程的threadId,然后把对象头的锁标志位设置为偏向锁,比对是否是同一个线程ID即可,如果有其他线程获得,那么偏向锁消失。

  • 5.轻量级锁
    轻量级锁主要就是用CAS,它是把对象头的标识拷贝一份到自己的栈里面,然后将引用指向栈里面的拷贝,当操作完成的时候,再用CAS更改回去,成功则表示竞争到了锁。失败就会升级成重量级锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值