JAVA并发编程实战,第三章 对象的共享

3.1可见性

为了确保多个线程之间对内存写入的可见性,就必须使用同步机制

在没有同步的情况下,编译器、处理器以及运行时等都可能对操作的执行顺序进行一些意想不到调整。在缺乏足够同步的多线程程序中,想要对内存操作的执行顺序进行判断,几乎无法做出正确的结论

3.1.1失效数据


3.1.2非原子的64位操作

即使不考虑失效数据问题,在多线程环境下使用共享且可变的long和double等类型的变量也是不安全的,除非用volatile来声明或者用锁来保护


3.1.3加锁和可见性

加锁的含义不仅仅是互斥行为,还包括内存可见性,为了确保所有线程都能够看到修改后的最新值,所有执行读操作或者写操作的线程都必须在同一个锁上进行


3.1.4Volatile

编译器和运行时都会注意到这个变量时共享的,因此不会将该变量上的操作与其他操作一起重排序

不会造成线程阻塞,是一种比Synchronized更轻量级的锁机制

volatile变量不会被缓存到寄存器或者其他处理器不可见的地方

仅当volatile变量能够简化代码的实现以及对同步策略的验证时,才应该使用它们

加锁机制既能保证原子性又能保证可见性,而volatile只能保证可见性


当且仅当满足以下条件时,才使用volatile

a.当对变量的写入操作不依赖当前变量的值,或者你能够确保只有单个线程更新变量的值

b.该变量不会与其他变量一起纳入不变性条件中

c.在访问变量时不需要加锁


3.2发布与逸出

发布一个对象的意思是指使对象能够在当前作用域之外的代码使用


例如:

将一个指向对象的引用放到其他代码可以访问的地方

一个非私有的方法中返回对象引用

引用传递到其他类的方法


当某个不应该被发布的对象被发布时,就叫做逸出


发布对象最简单的方式就是讲对象的引用保存到一个公有的静态变量中


当发布某个对象时,可能间接的发布其他对象

当发布某个对象时,该对象的非私有域中的所有对象同样会被发布

当把某个对象发布到外部方法时,就相当于发布了这个对象

发布一个内部的类实例也可以发布对象或内部状态


安全的对象构造过程:

不要再构造过程中使用this引用逸出

使this引用逸出最常见错误是,在构造函数中启动一个线程

使用私有构造函数和一个公共工厂方法防止this引用在构造函数中逸出


3.3线程封闭

如果仅在单线程内访问数据,就不需要同步,这种技术叫做线程封闭


应用场景

Swing中大量使用

JDBC的Connection对象


机制

局部变量

ThreadLocal


3.3.1Ad-hoc线程封闭

定义:指维护线程封闭性的职责完全由程序实现来承担

由于Ad-hoc线程封闭的脆弱性,因此程序中尽量少用


3.3.2栈封闭

在栈封闭中,只能通过局部变量访问对象

对于基本类型的局部变量,无论如何都 不会破坏栈的封闭性

在维持对象引用的栈封闭时,要确保引用对象不会逸出


3.3.3ThreadLocal类

通常用户对可变的单实例对象或者全局变量进行共享


3.4不变性

不可变对象一定是线程安全的


对象不可变应该满足的条件

a.对象创建以后其状态就不能修改

b.对象的所有域嗾使final

c.对象时正确创建的(在对象创建期间,this引用没有逸出)


在不可变对象的内部仍可以用可变的对象来管理他们的状态

3.4.1Final域

除非需要更高的可见性,否则将对象所有域声明为私有域是一个良好的编程习惯

除非需要某个域是可变的,否则将其声明为final也是一个良好的编程习惯


3.4.2示例:使用volatile类型来发布不可变的对象


3.5安全发布

3.5.1不正确的发布:正确的对象被破坏


3.5.2不可变对象和初始化安全性

任何线程都可以在不需要额外同步的情况下安全地访问不可变对象,即使在发布这些对象时没有使用同步


3.5.3安全发布的常用模式

要安全的发布一个对象,对象的引用以及对象的状态必须同时对其他线程可见。一个正确构造的对象可以通过以下方式安全的发布

a.在静态初始化函数中初始化一个对象引用

b.将对象的引用保存到volatile类型的域或者AtomicRererance对象中

c.将对象的引用保存到某个正确构造对象的final域中

d.将对象的引用保存到一个由锁保护的域中


线程安全的容器类提供了以下安全发布的保证

a.通过将一个键或者值放入一个hashTable、synchronizedMap或者ConcurrentMap中,可以安全的将它发布给任何从这些容器中访问它的线程(无论是直接访问还是通过迭代器访问)

b.通过将一个元素放入到Vector、CopyOnWriteArrayList、CopyOnWriteArraySet、SynchronizedList或者SynchronizedSet中,可以将元素发布到任何从这些容器中访问它的线程

c.通过将元素放到BlockingQueue或者ConcurrentLinkedQueue中,可以将元素安全的发布到任何从这些队列中访问该元素的线程

d.通过静态的初始化器初始化的任何对象都被安全发布


3.5.4事实不可变对象

如果对象从技术上来说是可变的,但其状态在发布后不会发生变化,把这种对象称为事实不可变对象

在没有额外的同步的情况下,任何线程都可以安全的使用被安全发布的事实不可变对象


3.5.5可变对象

对象的发布需求取决于它的可变性

不可变对象可以通过任意机制来发布

事实不可变对象必须通过安全方式来发布

可变对象必须通过安全方式来发布,并且必须是线程安全的或者由某个锁保护起来


3.6安全的共享对象

当发布一个对象时,必须明确对象访问方式


在并发程序中使用和共享对象时,可以使用一些实用的策略

线程封闭:对象只能由一个线程拥有,对象被封闭在线程中,并且只能由这个线程修改

只读共享:在没有额外同步的情况下,共享的只读对象可以由多个线程并发访问,但任何线程不能修改它。共享的只读变量包括不可变对象和事实不可变对象

线程安全共享:线程安全的对象在其内部实现同步,因此多个线程可以通过对象的公有接口来进行访问而不需要进一步同步

保护对象:被保护的对象只能通过持有特定的锁来访问,保护对象包括封装在其他线程安全对象中的对象,以及已发布并且由某个特定锁保护的对象



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

推荐阅读更多精彩内容