java多线程编程基础二(同步机制)

java提供的线程同步机制:锁、volatile关键字、final关键字、static关键字以及相关的API(如Object.wait/Object.notify)。

1、锁(Lock):

使多线程对共享数据(共享变量、共享资源)的并发访问,变为串行访问。

  • 锁具有排它性,一次只能被一个线程所持有。(互斥性)
  • 一个线程在访问共享数据时必须申请相应的锁,获得锁的线程称为锁的持有线程。
  • 锁的持有线程在获得锁之后到释放锁之前,所执行的代码,称为临界区
按照锁的实现方式不同分为:

a、内部锁(intrinsic Lock),通过synchronized关键字实现
b、显式锁(explicit lock),通过java.concurrent.locks.Lock接口的实现类实现

锁相关的概念:

a、可重入性:如何一个线程持有一个锁的时候,能够继续成功申请该锁,即为可重入(Reentrant),否则不可重入(Non-reentrant)
b、锁的争用和调度:锁可以看做多线程访问共享数据时所需要持有的一种排他性资源。

java中锁的调度策略:公平锁(内部锁),非公平锁(显式锁既支持公平锁,也支持非公平锁)

c、锁的粒度:一个锁可以保护一个或多个共享数据,一个锁所保护的共享数据的数量大小被称为锁粒度

锁的开销,及锁的问题:

锁的开销包括锁的申请和释放所产生的开销,以及锁可能导致上下文切换所产生的开销

锁存在被争用的情况,一旦发生争用,就会出现上下文切换的问题,未被争用的锁不会导致上下文切换

锁导致的线程活性故障:

a、锁泄露(lock leak):指一个线程在获取锁之后,由于程序错误,一致无法释放锁,从而导致其他线程无法正常获取锁。
b、死锁
c、锁死

内部锁和显式锁的区别:

a、灵活性,内部锁就是同步代码块,要么使用,要么不使用;显式锁是基于对象的锁,相对灵活。内部锁的锁获取和释放只能在代码块中执行,而显式锁能在一个方法中获取锁,而在另一个方法中释放锁。
b、易用性,内部锁简单易用,不会导致锁泄露;而显式锁由于锁的获取到释放灵活多变不好掌控
c、显式锁新增了针对锁的监控,而内部锁Thread.holdsLock(Object)只能检测当前线程是否持有指定的内部锁。
d、Java1.6/1.7 对内部锁做了一些优化,这些优化在特定情况下可以减少锁的开销。这些优化包括锁消除(Lock Elimination)、锁粗化(Lock Coarsening)、偏向锁(Biased Lock)和适配性锁(Adaptive Lock)。而这些优化在Javal.6/1.7中并没有运用到显式锁上。
e、在Javal.5中,在高争用的情况下,内部锁的性能急剧下降,而显式锁的性能下降则少得多。换而育之,Java1.5中显式锁的可伸缩性(Scalability)比内部锁的可伸缩性要好。到了Java1.6,随着JDK对内部锁所做的一些改进,显式锁和内部锁之间的可伸缩性差异已经变得非常小了。

改进型锁:读写锁(read/wirte lock)是一种改进型的排他锁,也被称为共享/排他锁。

读写锁允许多个线程可以同时读取(只读)共享变量,而只允许一个线程更新共享变量;读取共享变量时,其它线程不允许更新共享变量,并且更新共享变量时,其它线程不可访问共享变量

对于同步在同一锁之上的线程而言,对共享变量仅进行读取而没有进行更新的线程被称为只读线程,简称读线程。对共享变量进行更新(包括先读取后更新)的线程就被称为写线程。

ReentrantReadWriteLock(读写锁),是一个可重入锁。其支持锁的降级(DownGrade),即一个线程获取写锁之后,可以继续获得相应的读锁;但是不支持锁的升级(UpGrade),即一个线程持有读锁的情况下,不能继续获取相应的写锁。

2、内存屏障(线程同步机制的底层实现):

锁保证可见性的实现方式(即获取锁和释放锁的内存逻辑):
a、刷新处理器缓存(保证在锁的持有线程在读取共享数据之前更新内存数据,保证数据的读写正确)
b、冲刷处理器缓存(保证在锁的持有线程在释放锁之后,共享数据对其它线程的可见性)
这两步操作是借助内存屏障实现的。

约定:对于同步在同一个锁之上的多个线程,我们称对共享变量进行更新的线程为写线程,对共享变量进行读取的线程为读线程。因此,一个线程可以既是写线程又是读线程。读线程、写线程在访问共享变量时必须持有相应的锁。

内存屏障是被插入到两个指令之间进行使用的,其作用是禁止编译器、处理器重排序从而保障有序性

3、锁与重排序:

多线程,使用锁状态下的编译器和处理器的重排序规则:
a、临界区内的操作不允许重排序到临界区之外
b、临界区内的操作之间允许被重排序
c、临界区外的操作之间允许被重排序
d、锁申请与锁释放不允许被重排序
e、两个锁申请操作不允许被重排序
f、两个锁释放操作不允许被重排序
g、临界区外的操作可以被重排序到临界区内(与编译器的实现规则有关,JIT是不会将临界区外的操作重排序的临界区内的)

4、volatile轻量级同步机制

volatile关键字修饰的变量不会被编译器分配到寄存器进行存储,并且读写操作都是内存访问(访问高速缓存相当于主内存)操作

volatile被称为轻量级锁的原因是:

  • volatile保证了可见性、有序性,但是没有锁的排它性。
  • volatile不会引起上下文的切换。

volatile 关键字的作用包括:保障可见性、保障有序性和保障long/double 型变量读写操作的原子性。

volatile 关键字在原子性方面仅保障对被修饰的变量的读操作、写操作本身的原子性。如果要保障对volatile变量的赋值操作的原子性,那么这个赋值操作不能涉及任何共享变量(包括被赋值的volatile变量本身)的访问。

5、对象的发布和逸出

对象的发布是指使对象能够在器作用域之外的线程访问

对象发布的形式:

a、private修饰的对象
b、将对象存储到public变量中
c、非private方法中返回一个对象
d、创建内部类,使得当前对象能够被这个内部类使用
e、通过方法调用将对象传递给外部方法

对象的初始化安全:

a、使用static 关键字修饰引用该对象的变量:仅保证读线程能读到相应字段的初始值,而不是最新值
b、使用final 关键字修饰引用该对象的变量:当一个对象的引用对其他线程可见的时候,这些线程所看到的该对象的final 字段必然是初始化完毕的。final c、关键字的作用仅是这种有序性的保障,它并不能保障包含final 字段的对象的引用自身对其他结程的可见性。
d、使用volatile关键字修饰引用该对象的变量。
e、使用Atomic Reference 来引用该对象。
f、对访问该对象的代码进行加锁。

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

推荐阅读更多精彩内容