Java锁理解-synchronized和lock

synchronized

        synchronized主要基于monitor区进行锁的获取。

        Java对象头中有个mark word区域,在32位的情况下,当一个线程总是获得锁的时候,前23位会纪录偏向锁的线程id,此后该线程再次获取锁的时候,只需CAS验证一下线程id是否相同就可以直接获取对象的锁。锁标志位是101.

        当有其他线程开始竞争的时候,这时偏向锁会升级成轻量级锁,此时对象头的mark word存储锁记录表的指针,该指针指向获得当前对象锁的线程的虚拟机栈,锁记录表用于记录,恢复对象mark word相关信息,此时锁标志位00.

        当继续有多线程竞争对象锁的时候,此时轻量级锁会升级成重量级锁,会在堆区开辟当前对象对应的monitor区间,通过monitorenter和monitorexit进行加锁和解锁。此时对象的mark word存储monitor区的地址,锁标志为10。

        monitor区主要几个参数为:

                 -count : 记录对象进入monitor区的次数(synchronized是隐式可重入锁的体现)

                -owner : 表示当前拥有对象锁的线程

                -entrylist: 其他线程阻塞等待获取对象锁的列表

                -seqtime: 其他线程自旋去询问获取锁的时间间隔

                -seqCount:其他线程自旋去询问获取锁的时间间隔

                -waitList: synchronzied中调用wait(),阻塞的队列,此时需要notify才能唤醒

lock

        lock一个可控的加锁解锁的接口

        AQS(abstractQueueSynchronlizer):一个同步队列器,各种锁和并发工具类都是基于AQS去自定义控制实现。AQS 维护一个 volatile的变量state,通过 get set CASsetState来控制这个state变量。通过一些,acquire release(share.intruptter)等方法来实现锁的获取和释放,封装了底层的实现,提供这些模板方法供给自定义类得实现。

        提供的一些模板方法,tryAcquire,tryRelease(share),isHeldExclusively(是否被当前线程独占)

        维护了一个同步队列,对象是node,通过前驱和后驱节点来实现,队列元素的控制,即加锁和解锁。

        底层通过native类的park和unpark方法进行线程的阻塞和唤醒。

        

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值