Java变量用final修饰的变量一定是线程安全的吗?

简介: Java变量用final修饰的变量一定是线程安全的吗?

正文


常理上,用final修饰的变量具有内存可见性的特点,而且是不会变化的,可以保证他是不可变的。但是,仅仅是在是在一个不可变的对象在正确的创建的出来,才是线程安全的。

那什么时候,是不正确的创建方式呢?答案就是:在创建的过程中,有没有发生this的引用逃逸的情况。

引用逃逸:在构造器构造还未彻底完成前(即实例初始化阶段还未完成),将自身this引用向外抛出并被其他线程复制(访问)了该引用,可能会问到该还未被初始化的变量,甚至可能会造成更大严重的问题。(发生的概率较小,但是并不表示不会发生)。

1.png

输出:这说明ThisEscape还未完成实例化,构造还未彻底结束。


发生空指针错误:普通变量j未被初始化
发生空指针错误:final变量i未被初始化

另一种情况是利用线程A模拟this逃逸,但不一定会发生(小概率事件一定会发生的),线程A模拟构造器正在构造...而线程B尝试访问变量,这是因为

(1)由于JVM的指令重排序存在,实例变量i的初始化被安排到构造器外(final可见性保证是final变量规定在构造器中完成的);

(2)类似于this逃逸,线程A中构造器构造还未完全完成。

如下面的代码:

2.png

所以,用final修饰的对象并不一定线程安全的,任何的代码所说的安全都是在一定范围、一定条件下所说的线程安全。

相关文章
|
21小时前
|
安全 Java
【JAVA进阶篇教学】第十篇:Java中线程安全、锁讲解
【JAVA进阶篇教学】第十篇:Java中线程安全、锁讲解
|
22小时前
|
安全 Java
【JAVA进阶篇教学】第六篇:Java线程中状态
【JAVA进阶篇教学】第六篇:Java线程中状态
|
22小时前
|
缓存 Java
【JAVA进阶篇教学】第五篇:Java多线程编程
【JAVA进阶篇教学】第五篇:Java多线程编程
|
22小时前
|
Java
【JAVA基础篇教学】第十二篇:Java中多线程编程
【JAVA基础篇教学】第十二篇:Java中多线程编程
|
23小时前
|
安全 Java
java-多线程学习记录
java-多线程学习记录
|
2天前
|
Java
【Java多线程】面试常考 —— JUC(java.util.concurrent) 的常见类
【Java多线程】面试常考 —— JUC(java.util.concurrent) 的常见类
10 0
|
2天前
|
设计模式 消息中间件 安全
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
8 0
|
2天前
|
安全 Java 程序员
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
5 0
|
2天前
|
Java 数据库
【Java多线程】对线程池的理解并模拟实现线程池
【Java多线程】对线程池的理解并模拟实现线程池
10 1
|
2天前
|
Java
【Java多线程】分析线程加锁导致的死锁问题以及解决方案
【Java多线程】分析线程加锁导致的死锁问题以及解决方案
9 1