主要有下面三个加在类上的线程安全相关的注解。
一.@Immutable
标记一个类为不可变的。这意味着该类的实例在构造完成后,其状态(数据)永远不能被更改。实现不可变性的严格条件(Java内存模型中的定义):
所有字段都是
final
的:这确保了在构造函数执行完毕后,所有字段的引用对其他线程是可见的(通过final
的语义保障),并且引用不能再指向其他对象。类本身被声明为
final
:防止子类覆盖其方法并意外地改变状态(“破坏性继承”)。this
引用没有逸出:在构造函数执行期间,this
引用不能提供给其他代码,防止其他代码在对象完全构造之前就看到它。对可变状态的正确管理:
如果类包含对可变对象的引用(例如,一个final List<String>
),那么必须:
- 如果需要返回内部可变状态,返回其防御性拷贝,而不是原始引用。
- 不要提供任何可以修改这些可变状态的方法(如setter)。
- 在构造函数中,深度拷贝任何传入的可变参数,而不是直接存储其引用。
下面是注解源码:
可以发现有两个地方存在@Immutable注解,它们的来源不一样,我们应该使用第一个并发包下的注解。第二个不太稳定。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package javax.annotation.concurrent;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Immutable {
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package jdk.nashorn.internal.ir.annotations;public @interface Immutable {
}
总结
javax.annotation.concurrent.Immutable
:是公共的、受支持的、有用的并发编程工具注解,用于文档化和静态分析。jdk.nashorn.internal.ir.annotations.Immutable
:是内部的、已废弃的、特化的JDK实现细节注解,与应用程序开发无关。
二.@ThreadSafe
标记一个类是线程安全的。这意味着该类的实例可以在多线程环境下被安全地并发使用,其内部方法会维护状态的一致性。
实现方式(多种途径):
无状态:类没有任何字段,自然是线程安全的。(如:只包含静态工具方法的类)。
使用不可变状态:即类本身是
@Immutable
的。使用内置锁 (
synchronized
):通过同步方法或同步代码块来保护所有访问状态的临界区。使用并发容器:例如,使用
ConcurrentHashMap
代替HashMap
,使用AtomicInteger
代替int
。使用显式锁 (
java.util.concurrent.locks.Lock
):提供更灵活的锁定机制。
下面是concurrent包下的
注解源码。(其实java中还有别的@ThreadSafe注解,问题与上面一个注解类似,有不同的来源,主要使用下面这个)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package javax.annotation.concurrent;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface ThreadSafe {
}
三.@NotThreadSafe
明确标记一个类是非线程安全的。这意味着该类的实例不能在多线程间共享,除非由调用者通过外部手段(如外部同步)来协调访问。
为什么需要它?
默认情况:Java中的大多数类(如
ArrayList
,HashMap
,StringBuilder
)默认都是非线程安全的,以实现最佳性能。明确警示:加上此注解是一个非常好的实践,它明确地告诉使用者:“注意!这个类不是线程安全的,你不能直接在多线程环境下使用它”,避免了潜在的误用和难以发现的并发Bug。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package javax.annotation.concurrent;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface NotThreadSafe {
}