java并发编程中实现可见性的四种可行方案解析

 更新时间:2023年08月07日 09:04:53   作者:键盘林  
这篇文章主要介绍了java并发编程中实现可见性的四种可行方案解析,使用关键字volatile和使用锁(如synchronized关键字或者java.util.concurrent包中的锁)来确保对共享变量的修改在多线程环境中能够正确地被其他线程所观察到,需要的朋友可以参考下

在方法或者变量已经同步的情况下,还会出现什么问题吗?

多线程编程主要学的就是"互斥"和"可见","互斥"指的就是就是同步,而"可见"想必很多人还没有理解.

举个例子:

MyVolatile.java:

package cn.mxl.test.wr;
public class MyVolatile {
	private  int a=0;
	public   void write() throws InterruptedException {
		a++;
		System.out.println("当前线程:"+Thread.currentThread().getName());
		System.out.println(a);
	}
	public   void read() throws InterruptedException {
		while(a==0) {
//			Thread.sleep(1);
//			System.out.println(a);
		}
		System.out.println("当前线程:"+Thread.currentThread().getName());
		System.out.println(a);
	}
}

MyRead.java:

package cn.mxl.test.wr;
public class MyRead implements Runnable{
	private MyVolatile task;
	public MyRead(MyVolatile task) {
		// TODO Auto-generated constructor stub
		this.task=task;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		try {
			task.read();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

MyWrite.java:

package cn.mxl.test.wr;
public class MyWrite implements Runnable{
	private MyVolatile task;
	public MyWrite(MyVolatile task) {
		// TODO Auto-generated constructor stub
		this.task=task;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		try {
			task.write();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

Run.java:

package cn.mxl.test.wr;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
public class Run {
	public static void main(String[] args) throws Exception, ExecutionException {
		MyVolatile task=new MyVolatile();
		MyWrite mt1=new MyWrite(task);
		MyRead mt2=new MyRead(task);
		Thread tW=new Thread(mt1,"Write");
		Thread tR=new Thread(mt2,"Read");
		tR.start();
		Thread.sleep(2000);
		tW.start();
	}
}

运行结果:

Read线程一直处于a==0中是为什么呢?

因为当Read线程 先开始线程的时候,加载主内存中的数据放到自己的私有内存中,在程序执行过程中为了提高效率,它就只读自己私有内存中的数据,不会再去读主内存中的共享数据,在这个过程中,主内存对于该线程来说,只写不读,也就是说将自己修改的变量值存放到主内存中,但是自己不去读主内存的数据;所以说,在Read线程执行到while语句一直循环的时候,即使Write线程修改a==1值了,Read线程还是之前a==0的值,一直跳不出循环;

解决办法-->可见性,让Read线程读a变量的时候去主内存(共享数据)中读取:

volatiel关键字的使用:

MyVolatile.java:

package cn.mxl.test.wr;
public class MyVolatile {
	private volatile  int a=0;
	public   void write() throws InterruptedException {
		a++;
		System.out.println("当前线程:"+Thread.currentThread().getName());
		System.out.println(a);
	}
	public   void read() throws InterruptedException {
		while(a==0) {
//			Thread.sleep(1);
//			System.out.println(a);
		}
		System.out.println("当前线程:"+Thread.currentThread().getName());
		System.out.println(a);
	}
}

结果:

其实在这个过程中,我遇到了一些有趣的事情,可见性这东西,其实还有三个东西可以实现:

第一个-->Thread.sleep():

MyVolatile.java(取消sleep的注解):

package cn.mxl.test.wr;
public class MyVolatile {
	private   int a=0;
	public   void write() throws InterruptedException {
		a++;
		System.out.println("当前线程:"+Thread.currentThread().getName());
		System.out.println(a);
	}
	public   void read() throws InterruptedException {
		while(a==0) {
			Thread.sleep(1);
//			System.out.println(a);
		}
		System.out.println("当前线程:"+Thread.currentThread().getName());
		System.out.println(a);
	}
}

 结果:

第二个是system.out.println():

MyVolatile.java:

package cn.mxl.test.wr;
public class MyVolatile {
	private   int a=0;
	public   void write() throws InterruptedException {
		a++;
		System.out.println("当前线程:"+Thread.currentThread().getName());
		System.out.println(a);
	}
	public   void read() throws InterruptedException {
		while(a==0) {
//			Thread.sleep(1);
			System.out.println(a);
		}
		System.out.println("当前线程:"+Thread.currentThread().getName());
		System.out.println(a);
	}
}

 结果:

 第三个atomic:

MyVolatile.java:

package cn.mxl.test.wr.atomic;
import java.util.concurrent.atomic.AtomicInteger;
public class MyVolatile {
	private   AtomicInteger a=new AtomicInteger();
	public   void write() throws InterruptedException {
		a.incrementAndGet();
		System.out.println("当前线程:"+Thread.currentThread().getName());
		System.out.println(a);
	}
	public   void read() throws InterruptedException {
		while(a.get()==0) {
//			Thread.sleep(1);
//			System.out.println(a);
		}
		System.out.println("当前线程:"+Thread.currentThread().getName());
		System.out.println(a);
	}
}

结果:

到此这篇关于java并发编程中实现可见性的四种可行方案解析的文章就介绍到这了,更多相关java实现可见性内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 浅谈MyBatis 如何执行一条 SQL语句

    浅谈MyBatis 如何执行一条 SQL语句

    Mybatis 是 Java 开发中比较常用的 ORM 框架。在日常工作中,我们都是直接通过 Spring Boot 自动配置,并直接使用,但是却不知道 Mybatis 是如何执行一条 SQL 语句的,下面就一起讲解一下
    2021-05-05
  • Java序列化与反序列化的实例分析讲解

    Java序列化与反序列化的实例分析讲解

    今天小编就为大家分享一篇关于Java序列化与反序列化的实例分析讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Java 死锁解决方案顺序锁和轮询锁

    Java 死锁解决方案顺序锁和轮询锁

    这篇文章主要介绍了Java 死锁解决方案顺序锁和轮询锁,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-05-05
  • java开发中基于JDBC连接数据库实例总结

    java开发中基于JDBC连接数据库实例总结

    这篇文章主要介绍了java开发中基于JDBC连接数据库的方法,以实例形式较为详细的总结分析了Java使用JDBC的具体步骤与注意事项,并附带了一个完整实例加以说明,需要的朋友可以参考下
    2015-11-11
  • Mybatis-Plus实现自定义SQL具体方法

    Mybatis-Plus实现自定义SQL具体方法

    Mybatis-Plus是Mybatis的一个增强工具,它可以优化我们的开发效率,这篇文章主要介绍了Mybatis-Plus实现自定义SQL,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2023-08-08
  • Spring Security 控制授权的方法

    Spring Security 控制授权的方法

    本篇文章主要介绍了Spring Security 控制授权的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • SpringBoot集成内存数据库H2的实践

    SpringBoot集成内存数据库H2的实践

    h2是内存数据库,查询高效,可以在开发初期使用它。本文主要介绍了SpringBoot集成内存数据库H2的实践,具有一定的参考价值,感兴趣的可以了解一下
    2021-09-09
  • Spring boot 应用实现动态刷新配置详解

    Spring boot 应用实现动态刷新配置详解

    这篇文章主要介绍了spring boot 配置动态刷新实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2021-09-09
  • idea替换快捷键,批量处理对象的操作

    idea替换快捷键,批量处理对象的操作

    这篇文章主要介绍了idea替换快捷键,批量处理对象的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • 解决Netty解码http请求获取URL乱码问题

    解决Netty解码http请求获取URL乱码问题

    这篇文章主要介绍了解决Netty解码http请求获取URL乱码问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06

最新评论