举个不安全的发布对象例子,比如我们创建一个类是下面的方式创建,那么则属于不安全发布对象,就是说这个类压根不安全,使用的时候会导致在多线程环境下不安全
package com.example.gaobinfa.publish;
import com.example.gaobinfa.annoations.NotThreadSafe;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
/**
* 这个写法的类就是不安全对象的发布方式
* 不安全的发布对象的例子
*/
@Slf4j
@NotThreadSafe
public class UnsafePublish {
private String[] states = {"a", "b", "c"};
/**
* 这里idea编辑器直接回报一定的警告,提示警告,大概意思是:
* 访问权限将上面的private修饰的states暴露出了,有安全隐患
*
* @return
*/
public String[] getStates() {
return states;
}
public static void main(String[] args) {
UnsafePublish unsafePublish = new UnsafePublish();
log.info("{}", Arrays.toString(unsafePublish.getStates()));
unsafePublish.getStates()[0] = "d";
log.info("{}", Arrays.toString(unsafePublish.getStates()));
//打印结果日志如下
// 21:43:08.418 [main] INFO com.example.gaobinfa.publish.UnsafePublish - [a, b, c]
// 21:43:08.423 [main] INFO com.example.gaobinfa.publish.UnsafePublish - [d, b, c]
}
}
再举个不安全发布对象(溢出)的例子
package com.example.gaobinfa.publish;
import com.example.gaobinfa.annoations.NotRecommend;
import com.example.gaobinfa.annoations.NotThreadSafe;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@NotThreadSafe//线程不安全自定义注解
@NotRecommend//不推荐自定义注解
public class Escape {
private int thisCanBeEscape = 0;
public Escape () {
//这里后面的this的使用相当于隐式的线程
new InnerClass();
}
private class InnerClass {
public InnerClass() {
//这里有不安全的因素,应该使用工厂方法或者构造方法创建
log.info("{}", Escape.this.thisCanBeEscape);
}
}
public static void main(String[] args) {
new Escape();
// 打印结果的日志
// 21:49:18.249 [main] INFO com.example.gaobinfa.publish.Escape - 0
}
}
安全发布对象,在经典著作java并发编程与实战中,提的是4种,
3种分别在单例模式体现,可以参考单例模式 https://blog.csdn.net/wozniakzhang/article/details/85222414
另一种是将对象的引用保存到某个正确构造对象的final类型域中