[Java并发编程实战] 第3章 对象的共享

可见性:
  • 缺乏同步可能产生:失效数据

  • 最低安全性:当线程在没有同步的情况下读取变量时,可能得到一个失效值,但至少是之前某个线程设置的值,而不是一个随机值

  • 最低安全性的例外:非volatile类型的64位数值变量,所以多线程共享可变的long和double等类型的变量是不安全的,除非用volatile声明,或用锁保护起来

  • 加锁的含义不仅局限于互斥行为,还包括内存可见性。为了确保所有线程都能看到共享变量的最新值,所有执行读操作或写操作的线程都必须在同一个锁上同步

  • 访问volatile变量不会执行加锁操作,也就不会是执行线程阻塞,因此volatile变量是一种比sychronized关键字更轻量级的同步机制

  • 加锁可以确保可见性与原子性,volatile只能确保可见性

  • 当且仅当满足以下所有条件才应该用volatile:

    • 对变量的写入不依赖变量当前值,或者能保证只有单个线程更新变量的值
    • 该变量不会与其他状态变量一起被纳入不变性条件
    • 在访问变量时不需要加锁
发布与逸出
  • 发布对象:使对象能在当前作用域之外的代码中使用

  • 发布对象的方法:

    • 将对象引用保存到一个公有的静态变量中
    • 发布某个对象可能会间接发布其他对象
    • 从非私有方法中返回一个引用
    • 发布一个对象,该对象的非私有域中引用的所有对象都会被发布
    • 发布一个内部的类实例
  • 外部方法:对类C来说,外部方法指行为不完全由C来规定的方法,包括其它类中定义的方法和C中可以被改写的方法(不是private或final的方法)

  • this引用逸出的几种情况:

    • 在构造函数中引入了一个内部类EventListener,而内部类会自动的持有其外部类(这里是ThisEscape)this引用。source.registerListener会将内部类发布出去,从而ThisEscape.this引用也随着内部类被发布了出去。

    • 构造函数中启动一个线程,this引用会被新创建的线程共享

    • 在构造函数中调用一个可改写的实例方法(既不是私有方法,又不是final方法)

线程封闭
  • Ad-hoc线程封闭:维护线程封闭性的职责完全由程序实现来承担(很脆弱,尽量少用)

  • 栈封闭:只能通过局部变量访问对象,多个线程访问一个方法,此方法中的局部变量都会被拷贝一份到线程栈中。所以局部变量是不被多个线程所共享的,也就不会出现并发问题

  • ThreadLocal类:使线程中某个值与保存值的对象关联起来,为每个使用该变量的线程存有一份独立的副本,防止对可变的单实例变量或全局变量进行共享

不变性
  • 满足以下条件的对象才是不可变的:

    • 对象创建后其状态就不能修改
    • 对象所有域都是final的
    • 对象是正确创建的
  • 不可变对象内部仍然可以使用可变对象来管理他们的状态

  • 不可变对象vs不可变的对象引用:保存在不可变对象中的程序状态仍然可以更新,即通过一个保存新状态的实例来替换原有的不可变对象

  • 一个正确构造的对象可以通过以下方式安全发布:

    • 在静态初始化函数中初始化一个对象引用(静态初始化器由JVM在类的初始化阶段执行,由于JVM内部存在着同步机制,因此通过这种方法初始化的任何对象都可以被安全发布
    • 将对象的引用保存到volatile类型的域或AtomicReference对象中
    • 将对象引用保存到某个正确构造对象的final类型域中
    • 将对象引用保存到一个由锁保护的域中
  • 线程安全容器的安全发布保证:

    • 将一个键或者值放入Hashtable/synchronizedMap/ConcurrentMap中,可以安全地将它发布给任何从这些容器中访问它的线程
    • 将某个元素放入Vector/CopyOnWriteArrayList/CopyOnWriteArraySet/synchronizedList/sunchronizedSet中,可以将元素安全发布到任何从这些容器中访问该元素的线程
    • 将某个元素放入BlockingQueue/ConcurrentLinkedQueue中,可以将元素安全发布到任何从这些队列中访问该元素的线程
  • 事实不可变对象:对象从技术上看是可变的,但其状态在发布后不会改变

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

    • 不可变对象可以通过任意机制发布
    • 事实不可变对象通过安全方式发布
    • 可变对象通过安全方式发布,并且必须是线程安全的或者由某个锁保护起来
  • 并发程序中使用和共享对象,实用策略:

    • 线程封闭
    • 只读共享:不可变/事实不可变对象
    • 线程安全共享:内部同步
    • 保护对象:锁
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值