Java内存模型

Montior 锁

  1. 通过插入 monitorenter/monitorexit 来实现同步块
  2. 锁存在 Object Header 里的 Mark Word 上。Mark Word 无锁状态下存储分代信息,hashCode等。Mark Word 上2bit 的锁标志,表示当前的锁的类型

偏向锁

在mark word 中存储指向持有锁的线程的 id。

获取:

  1. 检查mark word 中的thead id 是否为自己,是则已经持有锁。
  2. 否则如果是处在可偏向状态,则尝试CAS 设置thread id
  3. 如果CAS 失败,则需要等到全局安全点,尝试撤销锁。检查持有锁的线程,将等待线程升级为轻量锁然后唤醒,或者如果持有锁的线程已经不再或有则尝试重新偏向。

轻量级锁

把mark word记录到自己的栈上,然后将mark word 替换为指向这条记录的指针。

  1. 复制mark word 到栈上
  2. 尝试CAS 替换mark word 为指向栈上记录的指针,如成功则成功加锁
  3. 如果失败,则尝试自旋一段时间,任然无法获取则膨胀微重量级锁
  4. 获取所得线程解锁时,唤醒对应的重量级锁

重量级锁

使用操作系统的锁。mark word 被替换为指向mutex 的指针。使用 pthread_cond_wait/pthread_cond_signal 来等待/唤醒线程

内存顺序

指令实际的内存执行顺序可以被三个因素影响

  1. 编译器优化重排序
  2. CPU 优化重排序
  3. CPU 缓存导致的重排序

对应阻止重排序的方法
遵循Java 的Happens-Before内存顺序模型

  1. 编译器。不重排序有前后依赖的指令。
  2. CPU。插入内存屏障

Happens before 模型

A happens before B 指。A 的内存操作对于B 可见

  1. 同一线程中,指令A 在 B 前面,则A happends before B
  2. 锁的获取happens before 锁的释放
  3. 一个voliate写happens before 另一个voliate读
  4. Thread A 里 start Thread B. 则 threadB.start() happens before 任意 thread 中的操作。
  5. Thread B 中的操作 happens before threadB.join()
  6. 遵循传递率。A happens before B, B happens before C 则 A happens before C

CPU 内存屏障

  1. LoadLoad
  2. LoadStore
  3. StoreStore
  4. StoreLoad

Volatile

内存语义

  1. volatile 写使得线程对应本地内存的共享变量被刷回主内存。
  2. volatile 读使得本地内存的共享变量无效,必须从主内存中读取。

实现方法

编译器层面

禁止volatile 操作和其他指令的重排

  1. volatile读 当前一个操作为volatile读时,禁止与后续操作重排
  2. volatile写 当后一个操作为volatile写时,禁止与前面的操作重排

CPU层面

插入内存屏障

  1. volatile读 在其后面插入 loadload, loadStore 屏障。使volatile读立即对接下来的操作可见
  2. volatile写 在前面插入 storestore, 后面加入storeload。使得volatile写之钱的写操作都可见。同时不会与后面可能的volatile读操作重排。

Final

对final 的赋值不会溢出 constructor。保证外界不会观察到final的值得变化。

例子

Double-Checked Locking (DCL)

错误原因,对共享变量赋值的部分,和检查获取共享变量的部分,没有同步。

instance = new Foo() 并非atmoic,需要

  1. 分配内存
  2. 使用constructor初始化
  3. 赋值给instance

step2, 3 可能被重排,导致其他线程获取到未初始化的实例

Solutions

  • volatile instance。禁止重排,保证可见
  • 将初始化代码移动到 class static block 中。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容