• 并发编程-synchronized


    synchronized锁什么?

     锁对象,可能包括:this, 临界资源对象,class类对象

    锁的底层实现

    同步代码块基于monitor enter和monitor exit指令实现同步,

    同步方法基于读取运行时常量池中方法的ACC_SYNCHRONIZED标志来隐式实现。

    对象内存的组成

    对象头:存储对象的hashcode锁信息GC信息类型指针

    实例变量

    填充数据:虚拟机要求对象的起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅为了字节对齐。

    执行过程

    当执行synchronized同步方法或同步代码块时,会在对象头中记录锁标记,锁标记指向monitor对象的起始地址。

    monotor对象:每个对象都存在一个monitor与之关联,monitor可以与对象一起创建销毁或当线程试图获取对象锁时自动生成。当monitor对象被某个线程持有后,便处于锁定状态

    monitor是由ObjectMonotor实现的。ObjectMonitor中包括:_owner标记,两个队列,_waitSet\_entryList

    所线程并发访问同一个同步代码时,首先进入_entryList, 当线程获取锁标记后,_owner记录此线程,且在monitor中的计数器执行+1操作代表锁定。其他线程在_entryList中继续阻塞。

    如果执行线程调用wait方法,则monitor中的计数器置为0,_owner置为null,代表放弃锁,执行线程进入waitset中阻塞。

    如果执行线程调用notify otifyAll,_waitset中的线程被唤醒,进入_entryList中阻塞,等待获取锁标记。

    如果执行线程的同步代码执行结束,会释放锁标记,monitor中的计数器置为0,_owner置为null

     

    在jdk1.6之前,synchronized使用的是重量锁。由于重量锁引起的线程阻塞唤醒开销太大,于是对此做了优化。

    先提供偏向锁,如果不满足的时候,升级为轻量级锁,再不满足,升级为重量级锁。

    锁只能升级,不能降级。

    偏向锁 : 它会偏向第一个访问锁的线程,如果不存在多线程竞争,是不需要触发同步的,这种情况下就会给线程加一个偏向锁。如果存在其他线程竞争,那么持有偏向锁的线程会被挂起,锁升级为轻量级锁。

    它通过消除资源无竞争情况下的同步原语,进一步提高了程序的性能。

    轻量级锁:先不把线程阻塞挂起前,先让线程空循环等待。轻量级锁适用于同步代码执行很快的场景,这样线程原地等待很短时间就能够获得锁了,而不需阻塞唤醒线程。

     

  • 相关阅读:
    使用C++与SFML编写一个简单的撞球游戏Part3——创建游戏启动界面
    生命游戏
    一道面试题
    为目标数字添加逗号分隔,由 baidu.number.comma 想到的
    制作JavaScript选择器(1)解析令牌
    Team Foundation 使用第三方比较工具
    Levenshtein Distance算法
    计算颜色的亮度值
    整理QUnit API
    Scrum笔记整理
  • 原文地址:https://www.cnblogs.com/yintingting/p/11424306.html
Copyright © 2020-2023  润新知