Java线程并发访问代码分析
这篇文章主要介绍了Java线程并发访问代码分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
class ConcurrentThread { /** * 分析线程并发访问代码解释原因 * volatile关键字: * 1):保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的 * 2):禁止进行指令重排序 * volatile本质是告诉JVM当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取 */ private volatile int count = 0; public void inc() { try { Thread.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } count++; } @Override public String toString() { return "[count=" + count + "]"; } } //---------------------------------------- public class VolatileTest { public static void main(String[] args) { final ConcurrentThread counter = new ConcurrentThread(); for (int i = 0; i < 1000; i++) { new Thread(new Runnable() { @Override public void run() { counter.inc(); } }).start(); } System.out.println(counter); } }
原因解释:在Java的内存模型中每一个线程运行时都有一个线程栈,线程栈保存了线程运行时候变量值信息
当线程访问某一个对象值得时候:
1、通过对象的引用找到对应在堆内存的变量的值
2、把堆内存变量的具体值load到线程本地内存中,建立了一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样堆中的对象的值就产生变化了。
结合上例,也就是说上面主函数中开启了1000个子线程,每个线程都有一个变量副本,每个线程修改变量只是临时修改了自己的副本,当线程结束时再将修改的值写入在主内存中,这样就出现了线程安全问题(拿到了主内存中过时的变量值),因此结果就不可能等于1000了,一般都会小于1000.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
相关文章
spring-cloud入门之spring-cloud-config(配置中心)
这篇文章主要介绍了spring-cloud入门之spring-cloud-config(配置中心),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2018-01-01maven-assembly-plugin报红无法加载报错:Plugin ‘maven-assembly-plugin
maven-assembly-plugin是一个常用的打包插件,但是在使用过程中经常会遇到各种报错,本文就来介绍一下maven-assembly-plugin报红无法加载报错,具有一定的参考价值2023-08-08SpringBoot 基于 MongoTemplate 的工具类过程详解
MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种,这篇文章主要介绍了SpringBoot基于MongoTemplate的工具类,需要的朋友可以参考下2023-09-09java 定时器Timer和TimerTask的使用详解(执行和暂停)
这篇文章主要介绍了java 定时器Timer和TimerTask的使用详解(执行和暂停),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧2023-11-11SpringMVC中的HandlerMappingIntrospector工具类详解
这篇文章主要介绍了SpringMVC中的HandlerMappingIntrospector工具类详解,这是一个Spring MVC助手类,用于集合应用所配置的HandlerMapping(url pattern和请求处理handler之间的映射)表,用于获取针对某个请求的如下信息,需要的朋友可以参考下2023-12-12
最新评论