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并发编程实战》是一本深入探讨Java平台并发编程的权威指南。这本书旨在帮助开发者理解和掌握在Java环境中创建高效、可扩展且可靠的多线程应用程序的关键技术和实践。它涵盖了从基本概念到高级主题的广泛内容,...
《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南,由Tim Peierls等人与Brian Goetz合著,旨在帮助Java开发者理解和掌握在多线程环境中编写高效、安全的代码。这本书由拥有丰富经验的JDK并发大师及...
《Java 并发编程实战》是一本专注于Java并发编程的权威指南,对于任何希望深入了解Java多线程和并发控制机制的开发者来说,都是不可或缺的参考资料。这本书深入浅出地介绍了如何在Java环境中有效地管理和控制并发...
这本书的读书笔记涵盖了多个关键知识点,旨在帮助读者深入理解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并发编程实践笔记知识点详解 #### 一、保证线程安全的方法 1. **不要跨线程访问共享变量:** 当多个线程共享某个变量时,若其中一个线程修改了该变量,其他线程若没有正确同步,则可能读取到错误的数据。...
第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平台的并发特性,编写出更高效、更可靠的多线程应用程序。无论是初级开发者还是经验丰富的专业人员,都能从这本书中收获宝贵的并发编程知识。
除了提供读者全面指南编写并发Java应用程序的书籍“Java Concurrency in Practice”外,还可以下载相关源代码。这包括书中使用的所有源代码示例,可以使用Maven轻松地将其导入Eclipse或IntelliJ IDEA中。通过实践源...
《Java 并发编程实战》是一本针对Java程序员深入学习并发编程的重要著作。这本书涵盖了从基础知识到高级技术的全面内容,旨在帮助读者理解和掌握多线程环境下的编程实践。书中结合了理论与实际示例,提供了丰富的...
3. 不可变共享值与多线程:不可变的共享值通常不会引发并发问题,但如果一个不可变对象的内部状态是可变的,或者依赖外部可变对象,同样需要进行适当的同步。 4. 多线程访问可变变量:如果没有适当的同步控制,将会...
《JAVA并发编程实践》这本书是Java开发者深入理解并发编程的重要参考资料。它涵盖了Java并发的核心概念、工具和最佳实践,旨在帮助读者在多线程环境下编写高效、安全的代码。 并发编程是现代软件开发中的关键技能,...
### Java并发编程实践 #### 一、并发编程基础 ##### 1.1 并发与并行的区别 ...通过上述知识点的学习,我们可以更好地理解和掌握Java并发编程的基本原理和技巧,为开发高效稳定的并发应用程序打下坚实的基础。
《Java 并发编程实战》是一本面向Java开发者的深度技术书籍,专注于讲解在多线程环境下如何有效地编写高效、安全的并发代码。这本书高清且带有详细的目录,方便读者快速定位到所需的主题,是Java并发编程领域的重要...