public class SynchronizedDemo{
//共享变量
private boolean ready = false;
private int result = 0;
private int number = 1;
//写操作
public void write(){
ready = true; //1.1
number = 2; //1.2
}
// 读操作
public void read(){
if (ready){ //2.1
result = number*3; //2.2
}
System.out.println("result的值为:" + result);
}
//内部线程类
private class ReadWriteThread extends Thread{
//根据构造方法中传入的flag参数,确定线程执行读操作还是写操作
private boolean flag;
public ReadWriteThread(boolean flag){
this.flag = flag;
}
@Override
public void run(){
if (flag)
{
//构造方法中传入true,执行写操作
write();
}
else{
//执行读操作
read();
}
}
}
public static void main(String[] args){
SynchronizedDemo synDemo = new SynchronizedDemo();
//启动线程执行写操作
synDemo.new ReadWriteThread(true).start();
//启动线程执行读操作
synDemo.new ReadWriteThread(false).start();
}
}
上面的代码结果可能是6,0
分析:
1.执行 顺序 1.1->2.1->1.2->2.2 result = 3
2.执行 顺序 1.2->2.1->.2.2->1.1 result = 0
3.可以自己分析其他情况
4.特殊:2.1和2.2是可以重排序的(2.1和2.2没有数据依赖关系,只有数据依赖关系才会禁止重排序)
2.1和2.2重排序后:
int mid = number*3;
if (ready){
result = mid;
}
可见性分析 synchronized解决方案
导致共享变量在线程间不可见的原因:
1.线程的交叉执行 ---> 原子性
2.重排序结合线程交叉执行 ---> 原子性
3.共享变量更新后的值没有在工作内存与主内存间及时更新 ---> 可见性
安全的代码:
//写操作
public synchronized void write(){
ready = true; //1.1
number = 2; //1.2
}
// 读操作
public synchronized void read(){
if (ready){ //2.1
result = number*3; //2.2
}
System.out.println("result的值为:" + result);
}
分析:
如果先执行了读线程再执行写程序 : 2.1 -> 2.2 -> 1.1 -> 1.2 result = 0
此时加了synchronized也没有用,没有牵扯线程交叉执行
所以,加入休眠,正确代码:
public static void main(String[] args){
SynchronizedDemo synDemo = new SynchronizedDemo();
//启动线程执行写操作
synDemo.new ReadWriteThread(true).start();
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
//启动线程执行读操作
synDemo.new ReadWriteThread(false).start();
}