Java之多线程内存可见性_2(synchronized实现可见性代码)

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();
  }




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值