《Java并发编程的艺术》&《Java并发编程实战》笔记

竞态条件

当某一个计算的值依赖于多个线程交替执行时序时,就会发生竞态条件。换句话说,就是正确的结果取决于运气。


复合操作

i++是一个复合操作,因为这其中包括了读取-修改-写入


处理器如何进行原子操作

1.锁住总线来保证原子性

所谓总线锁就是使用处理器提供一个Lock#信号,当一个处理器在总线上输出这个信号时。其他处理器的请求将会被阻塞,那么该处理器就可以独占内存

2.锁住缓存来保证完整性

在同一时刻,我们只需要保证对某一个内存地址的操作是原子性即可,但是总线锁把CPU和整个内存的通信都锁住了。

有两种情况不会使用缓存锁

1.处理器不支持锁住缓存

2.操作的数据不能存储在处理器内部

可重入锁

当一个线程请求获得请他线程的锁时,就会发生阻塞。然而,由于锁是可重入的,因此一个线程如果试图获得一个获得一个已经由他自己获得的锁时,这个请求就会成功,这就是锁的内置锁的重入。

重入的一种实现方法时,当一个锁被一个线程持有时,JVM就记下锁的持有者,并获取计数器,置为1.每次重入一次,计数器加一,释放一次减一。当计数器为0时,线程释放锁。

volatile

在Java中,如果一个字段被声明为了volatile,那么Java内存模型将确保所有的线程看到的这个变量都是一致的。还有,这个变量的读/写都将具有原子性

实现原理:被volatile修饰的字段,会比其他的变量多出一条lock前缀指令,前缀指令在多核处理器中会引发两件事情

1) 将当前处理器缓存行的数据写回系统内存

2) 这个写回内存的操作将会使其他CPU里缓存了该内存地址的数据无效。当处理器想要对该数据进行处理使用时,会重新从系统内存中把该数据读取到处理器缓存中去。


synchronized

同步锁。在Java SE 1.6以后为了减少获得锁和释放锁带来的性能消耗,引入了偏向锁和轻量级锁。

Java中任何一个对象都可以作为锁,具体表现为一下三种形式。

1) 对于普通的方法,锁住的是当前的对象

2) 对于被static修饰的静态方法,锁住的是该对象的Class对象

3) 对于同步代码块,锁住的则是括号中的对象

JVM基于进入和退出Monitor对象来实现方法同步和代码块同步。代码块同步是使用monitorenter和monitorexit指令来实现的,JVM必须保证每个monitorenter都有一个对应的monitorexit配对。JVM在同步代码开始的地方插入monitorenter,在异常和同步代码结束的地方插入monitorexit。任何一个对象都有一个monitor与之关联,当且一个monitor对象呗持有之后,它将处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象的monitor的所有权,即尝试获得对象的锁。

在Java对象头中存储着三种内存,分别是Mark Word,Class Medadata Address,Array length

Mark Word :存储对象的hashCode,锁信息,以及分代年龄

Class Medadata Address:存储指向对象类型的地址的指针

Array length:存储数组的长度(如果当前对象是数组的话)

在Java中锁一共有四种状态,无锁状态,偏向锁状态,轻量级锁状态,重量级锁状态,锁会随着竞争情况逐渐升级。只能升级,不能降级。


偏向锁

偏向锁在进入和退出同步代码块时不需要进行CAS操作来加锁或者解锁,只需要测试一下当前对象头的Mark Word中是否存储着当前线程的偏向锁。如果测试成功。表示已经获取了锁。如果测试失败,则需要再次测试一下Mark Word中的偏向锁标志位是否设置为1(表示当前是偏向锁),如果没有设置,就采用CAS竞争锁。如果没有设置,则尝试使用CAS将对象头中的偏向锁设置为当前线程

偏向锁的撤销:偏向锁采用了一种需要竞争才会释放锁的机制。当其他线程竞争锁时,持有偏向锁的线程才会释放锁。偏向锁的撤销需要在全局安全点执行(这个时间点没有字节码在执行)。它会首先暂停拥有偏向锁的线程,然后去检查偏向锁的线程是否还活着,如果死亡,则将锁的对象头设置为无锁状态。如果线程任然活着,那么拥有偏向锁的栈想会被执行,遍历对象的锁记录。栈中的锁记录和对象中的Mark Word要么重新偏向其他线程,要么标记为无锁状态或者标记对象不适合偏向锁。

上面的意思是,先暂停持有偏向锁的线程,尝试直接切换。如果不成功,就继续运行,并且标记对象不适合偏向锁,锁膨胀(锁升级)。                                                                                                                          


轻量级锁

线程首先在栈帧中创建用于存储锁对象对象头中的锁记录的空间,并且将Mark Word中的记录复制到所记录中去。然后使用CAS尝试将对象头中的Mark Word替换为指向锁记录的指针。如果成功,则表示当前线程获得了锁,如果失败则表示处于竞争状态,会采用CAS自旋来获取锁。

轻量级锁在解锁时,会尝试把对象头中的指针替换为Mark Word,如果成功,表示已经释放了锁。如果失败,则表示当前处于竞争条件下。锁就会膨胀为重量级锁

注意,轻量级锁会一直保持,唤醒总是发生在轻量级锁解锁时。因为加锁的时候CAS操作已经成功,而CAS失败的线程会立即锁膨胀,并且阻塞等待唤醒。


重量级锁

重量级锁在线程竞争是不会使用自旋,不会消耗CPU。缺点是线程阻塞,响应时间缓慢。使用的场景在是追求吞吐量和同步代码中执行速度的时候。

Java线程的中断

中断可以理解为一个标志位属性,它表示其他线程是否对该线程进行了中断操作。线程通过检查自身是否被中断来执行响应,线程通过isInterupt()来判断是否被中断。也可以调用静态方法Thread.interupted()来对当前线程的中断标志位进行复位。如果现场处于终结状态,那么即时该线程被中断过,也会返回false。

线程间的通信

通过volatile和synchronized关键字来保证线程之间的共享数据。

通过等待/唤醒机制来通信 

notify() nitifyAll() wait() wait(long) 等待超时的时间 毫秒 wait(long, int) 精确到纳秒

生产-消费者模式 一个线程修改了一个对象的值,而另外一个线程感知到了变化,然后进行相应的操作。

Thread.join()

当线程A执行了thread.join()的方法之后表示,当线程A等待thread线程终止之后才从join方法返回。

Lock

Lock与sychronized相比,特性是

1 可以尝试非阻塞式的获取锁       tryLock()

2 能够中断式的获取锁,获取到锁的线程能够响应中断,当获取到锁的线程被中断时,中断异常会被抛出,同时会释放锁。 lockInterruptibly();

3 能够超时获取锁 tryLock(long time, TimiUnit unit);

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

推荐阅读更多精彩内容