跟着实例学习java多线程4-内存可见性

并发编程 专栏收录该内容
10 篇文章 0 订阅

前三篇我们主要说了多线程访问共享可变状态时需要进行正确的同步处理,保证同一时刻只有一个线程访问相同的数据,我们使用synchronized关键字来实现原子性操作。

今天我们在来认识一下同步的另一个重要方面:内存可见性,这个概念其实很好理解,就是保证在同一个时刻,共享可变状态对访问它的线程呈现出自己最新的状态变化。

我们经常遇到的情景是这样的,一个全局变量计数器,一个线程负责更新该数值,另一些线程获取这个值,那么可见性就是获取值的线程,可以获取到更新线程更新的最新的值。

让我们先来看一个例子,在没有做同步的情况下会发生什么。

package com.home.thread;
/**
 * @author gaoxu
 * 
 */
public class ThreadStart {
 static boolean ready ;
 static int number;
 private static class ReaderThread extends Thread{
 
  public void run(){
   number = 1;
  }
 }
 private static class ReaderThread1 extends Thread{
  public void run(){ 
    if(ready){System.out.println("="+number);}
  }
 }
 
 public static void main(String[] para){
  
  new ReaderThread().start();
  ready = true;
  new ReaderThread1().start();
 }
}


以上这段代码的运行结果可能会呈现出以下的结果:

第一种:

=0

第二种

=1

这其中只有第二种是我们想要看到的结果。

我们把第一种情况现象叫做“重排序”,重排序现象往往会产生无效数据,第一行情况就是一个无效数据,解决这种现象就必须采用同步加锁机制。(当然还有volatile变量,以后我们会重点说一下)

下面我们看一下如何实现一个线程安全的可变整数类。

package com.home.thread;

/**
 * @author gaoxu
 * 
 */
@safe
public class SafeThread {
	static int number;
	

		@safe
	public  static synchronized int getNumber() {
		return number;
	}
	@safe
	public  static synchronized void setNumber(int number) {
		SafeThread.number = number;
	}
	
}
package com.home.thread;
/**
 * @author gaoxu
 * 
 */
public class ThreadStart {

 private static class ReaderThread extends Thread{
 
  public void run(){
   SafeThread.setNumber(1);
  }
 }
 private static class ReaderThread1 extends Thread{
  public void run(){ 
    System.out.println("="+SafeThread.getNumber());
  }
 }
 
 public static void main(String[] para){
  
  new ReaderThread().start();
  new ReaderThread1().start();
 }
}


加锁后我们会看到输出结果永远是 1了。

让我们总结一下加锁同步的含义:加锁的含义不仅仅局限于原子操作行为,还可以保证内存可见性。当然最重要的一点是多个读写线程必须是保证都在同一个锁上同步的操作可变状态变量。

我们现在了解完了同步的主要特性,互斥性和可见性。可是我们知道同步对性能的影响是非常大的,那么我们该怎么样平衡呢?


  • 0
    点赞
  • 1
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论 1 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

沉默andy

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值