1.内存可见性
synchronized关键字同步有两方面的作用:
(1)实现原子性或者确定临界区
(2)确保内存可见性
所谓内存可见性,即当一个线程修改了对象状态后,其他线程能够看到修改后的状态。
多线程程序在没有同步的情况下,编译器、处理器及运行时等都可能对操作执行顺序进行一些意想不到的调整。在缺乏足够同步的多线程程序中,要想对内存操作的执行顺序进行判断,几乎无法得出正确的结论。
1.1 失效数据
比如线程在没有同步的情况下读取变量时得到的可能是失效数据(之前某个线程设置的值)。
1.2 非原子的64位操作
非volatile的64位数值变量,比如long,double,JVM允许将64位的读操作或写操作分解为两个32位的操作。如果对该变量的读操作和写操作在不同的线程中执行,那么很可能读取到某个值的高32位和另一个值的低32位而导致错误。
1.3加锁与可见性
加锁的含义不仅包括互斥行为,还包括内存可见性,为了确保所有线程都能看到共享变量的最新值,所有执行读或写操作的线程都必须在同一个锁上同步。
1.4 volatile变量
volatile变量是一种稍弱的同步机制,用来确保将变量的更新操作通知到其他线程。
volatile变量只能确保可见性,而不能确保原子性。
2.发布与逸出
发布一个对象的意思是指,是对象能够在当前作用域之外的代码中使用。比如把该对象放到一个共有静态变量中,或者在非私有的方法中返回该对象的引用。
当某个不应该被发布的对象被发布时,这种情况称为逸出。
不要在对象构造过程中使this引用逸出,对象构造函数完成之前不要显示或隐式使用当前对象的引用。
3.线程封闭
3.1 Ad-hoc线程封闭
维护线程封闭的职责完全由程序实现来承担,比如只有单个线程对共享的volatile变量执行写入操作,即将写操作封闭在单个线程中以防止发生竞态条件,并且volatile变量的可见性还保证了其他线程能看到最新的值。
3.2 栈封闭
即使用局部变量,线程外部无法访问到局部变量。
3.3 ThreadLocal类
ThreadLocal对象能使线程中的某个值与保存的对象关联起来,ThreadLocal提供了get与set等访问接口或方法,为每个使用该变量的线程都存有一份独立的副本,get总是返回由当前执行线程在调用set时设置的最新值。
ThreadLocal对象通常用于防止可变的单实例变量或全局变量进行共享。
ThreadLocal类实现原理简要描述:
ThreadLocal类对象的值在初始化时,创建一个ThreadLocal.ThreadLocalMap对象,放在当前线程的threadLocals属性中,其中threadLocals的key是当前ThreadLocal对象,value是当前ThreadLocal对象的值。
4.不变性
不可变对象一定是线程安全的。
不可变对象需要满足的条件:
对象创建以后其状态就不能修改;
对象的所有域都是final类型;
对象是正确创建的(在对象的创建期间,this引用没有逸出)。
4.1 final域
final域不能修改,在java内存模型中,final还有特殊的语义:能确保初始化过程的安全性,从而可以不受限制的访问不可变对象,并在共享这些对象是无需同步。
4.2 使用volatile类型发布不可变对象
对于访问和更新多个变量时出现的竞争条件问题,可以通过将这些变量封装到一个不可变对象中,并使用volatile修饰变量确保可见性,而不必担心其他线程会修改对象的状态。
5.安全发布
不要在没有足够同步的情况下发布可变对象。
5.1 没有足够的同步,当在多线程间共享数据时将发生一些非常奇怪的事情。
5.2不可变对象与初始化安全性
任何线程都可以在不需要额外同步的情况下安全的访问不可变对象,即使在发布这些对象时没有使用同步。
这种保证还将延伸至这些对象的所有final域,在没有额外同步的情况下可以安全的访问final类型(final类型的域执行非可变对象的情况下)的域。
5.3 安全发布常用模式
要安全的发布一个对象,对象的引用及状态必须同时对其他线程可见,一个正确构造的对象可以通过以下的方式来安全的发布:
(1)在静态初始化函数中初始化一个对象引用。
(2)将对象的引用保存到volatile类型的域或者AutoReferance对象中。
(3)将对象的引用保存到某个正确构造对象的final类型域中。
(4)将对象的引用保存到一个由锁保护的域中。
通常要发布一个静态构造的对象,最简单和最安全的方式是使用静态的初始化器:
public static Holder holder = new Holder (66);
静态初始化器由JVM在类的初始化阶段进行,由于在JVM内部存在同步机制,因此通过这种方式初始化的对象都可以被安全的发布。
5.4 事实不可变对象
如果对象在发布后不会被修改,那么对于其他在没有额外同步的情况下安全的访问这些对象的线程来说,安全发布是足够的。
所有的安全机制都能够确保,当对象的引用对所有访问该对象的线程可见时,对象发布时的状态对所有线程也将是可见的,如果对象状态不会再改变,那么就足以确保任何访问都是线程安全的。
如果对象从技术上来看是可变的,但其状态在发布后不会再改变,这种对象称为“事实不可变对象”,在这类对象发布之后,程序只需将它视为不可变对象即可。
5.5 可变对象
如果对象在构造后可以修改,那么安全发布只能确保发布当时的状态可见性,所以对于可边对象,不仅在发布时需要同步,而且在每次访问时也需要使用同步来确保后续操作的可见性。
对象的发布需求取决于它的可变性:
不可变对象可以通过任意机制来发布;
事实不可变对象必须通过安全方式来发布;
可变对象必须通过安全方式来发布,并且必须是线程安全的或者由某个锁保护起来。
相关推荐
《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...
《Java并发编程实战》这本书是关于Java语言中并发编程技术的经典著作。它详细介绍了如何在Java环境中有效地实现多线程程序和并发控制机制。在Java平台上,由于其本身提供了强大的并发编程支持,因此,掌握并发编程...
《java并发编程实战》读书笔记-第3章-对象的共享,脑图形式,使用xmind8制作 包括可见性、发布与逸出、线程封闭、不可变性、安全发布等内容
《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南。这本书旨在帮助开发者理解和掌握在Java环境中创建高效、可扩展且可靠的多线程应用程序的关键技术和实践。它涵盖了从基本概念到高级主题的广泛内容,...
第3章 对象的共享 3.1 可见性 3.1.1 失效数据 3.1.2 非原子的64位操作 3.1.3 加锁与可见性 3.1.4 Volatile变量 3.2 发布与逸出 3.3 线程封闭 3.3.1 Ad-hoc线程封闭 3.3.2 栈封闭 3.3.3 ThreadLocal类 ...
综上所述,《Java并发编程实战》不仅涵盖了Java并发编程的基础知识和技术细节,还包含了丰富的实践经验和前瞻性的思考,是任何一位从事Java开发工作的程序员不可或缺的学习资源。无论是初学者还是有经验的开发者都能...
《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南,由Tim Peierls等人与Brian Goetz合著,旨在帮助Java开发者理解和掌握在多线程环境中编写高效、安全的代码。这本书由拥有丰富经验的JDK并发大师及...
这本书的读书笔记涵盖了多个关键知识点,旨在帮助读者深入理解Java并发编程的核心概念。 1. **线程和进程的区别** - **线程** 是程序执行的最小单位,一个进程中可以有多个线程同时执行,共享同一块内存空间,通信...
62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java...
《Java 并发编程实战》是一本专注于Java并发编程的权威指南,对于任何希望深入了解Java多线程和并发控制机制的开发者来说,都是不可或缺的参考资料。这本书深入浅出地介绍了如何在Java环境中有效地管理和控制并发...
《java并发编程实战》读书笔记-第3章-对象的共享,脑图形式,使用xmind8制作 包括线程安全类设计、实例封闭、线程安全性委托、现有线程安全类中添加功能和文档化同步策略等内容
JAVA并发编程实践中文版 英文版 原书源码 带书签 java_concurrency_in_practice.pdf 英文版还是不错的,但是中文版的译者典型的没有技术功底,介绍上说什么专家, 翻译的非常差劲,有些句子都不通顺,都不知道自己去...
《Java并发编程实战》是Java开发者深入理解和掌握并发编程的一本经典著作。这本书全面地介绍了Java平台上的并发和多线程编程技术,旨在帮助开发者在多核时代编写出高效、可伸缩且线程安全的代码。 并发编程是现代...
Java并发编程实战,第1章 简介,第2章 线程安全性 第3章 对象的共享 第4章 对象的组合 第5章 基础构建模块 第6章 任务执行 第7章 取消与关闭 第8章 线程池的使用 第9章 图形用户界面应用程序 第10章 避免...
第3章 对象的共享 3.1 可见性 3.1.1 失效数据 3.1.2 非原子的64位操作 3.1.3 加锁与可见性 3.1.4 Volatile变量 3.2 发布与逸出 3.3 线程封闭 3.3.1 Ad-hoc线程封闭 3.3.2 栈封闭 3.3.3 ThreadLocal类 3.4...
通过学习《JAVA并发编程实战》这本书,开发者可以掌握以上这些关键概念,并学会如何在实际项目中应用,避免并发编程中的陷阱,编写出高效、稳定的多线程程序。书中可能还会深入讨论线程安全的编程习惯、性能调优技巧...
根据提供的文件信息:“JAVA并发编程实战.pdf”,我们可以深入探讨与Java并发编程相关的多个核心知识点。 ### Java并发编程基础 #### 1. 并发与并行 - **并发(Concurrency)**:指一个程序中存在多个执行序列(如...