转载请注明出处 http://www.paraller.com 原文排版地址 点击获取更好阅读体验
核心知识点
可见性
重排序
``` class Test{ private static boolean visible; private static int number;
static class Reader extends Thread{
void run(){
while(!visible){
Thread.yield();
}
system.out.println(number);
}
}
static void main(String[] args){
new Reader().start();
number = 12;
visible = true;
}
} ```
Reader线程可能看到了visible的值,却没有看到number的,这种现象称为重排序
Jvm为了充分利用现代多核处理器,可能对操作的执行顺序进行调整
如何避免 : 只要有数据在线程之间共享,就使用正确的同步
Volatile
- 变量不会被缓存在寄存器或者其他处理器不可见的地方,在读取valatile变量时总会返回最新写入的值
- 变量声明为 volatile,编译器和运行时都会注意到这个变量是共享的,不会将该变量的操作与其他内存操作一起
重排序
使用场景:
检查某个状态标记以判断是否退出循环:(因为所有线程修改对其他线程都是可见) while(!asleep){ // TODO }
发布与逸出
核心知识点
- 发布的概念: 指对象能够在当前作用域之外的代码中使用.
- 发布内部的状态,会破坏封装性,会影响线程安全
- 逸出: 某个不应该被发布的对象被发布,就成为逸出(Escape)
- 当对象在其构造函数中创建一个线程时,this引用都会被新创建的线程共享;解决方案:在构造函数中创建但不是马上启动它,而是通过一个方法来启动。
- 避免逸出: 要返回一个对象A的时候,拷贝对应的值创建一个对象B,然后返回对象B。(可能在拷贝的时候A对象发生了改变,造成数据不一致,取决于需求是否这样使用)
逸出常见场景1: 将对象保存在共有的静态变量.
``` public static Set