首页 文章 精选 留言 我的

精选列表

搜索[扩展层],共10000篇文章
优秀的个人博客,低调大师

Java编程思想——多线程的三大核心源码层解密

欢迎大家关注,欢迎评论 对于Java并发编程,一般来说有以下的关注点: 1.线程安全性,正确性。 2.线程的活跃性(死锁,活锁) 3.性能 其中线程的安全性问题是首要解决的问题,线程不安全,运行出来的结果和预期不一致,那就连基本要求都没达到了。 保证线程的安全性问题,本质上就是保证线程同步,实际上就是线程之间的通信问题。我们知道,在操作系统中线程通信有以下几种方式: 1.信号量 2.信号 3.管道 4.共享内存 5.消息队列 6.socket java中线程通信主要使用共享内存的方式。共享内存的通信方式首先要关注的就是可见性和有序性。而原子性操作一般都是必要的,所以主要关注这三个问题。 1、原子性(Atomicity) 原子性是指在一个操作中就是cpu不可以在中途暂停然后再调度,既不被中断操作,要不执行完成,要不就不执行。 JMM只是保证了基本的原子性,但类似于i++之类的操作,看似是原子操作,其实里面涉及到: 获取 i 的值。 自增。 再赋值给 i。 这三步操作,所以想要实现i++这样的原子操作就需要用到synchronize或者是lock进行加锁处理。 如果是基础类的自增操作可以使用AtomicInteger这样的原子类来实现(其本质是利用了CPU级别的 的CAS指令来完成的)。 其中用的最多的方法就是:incrementAndGet()以原子的方式自增。 源码如下: 首先是获得当前的值,然后自增 +1。接着则是最核心的compareAndSet()来进行原子更新。 其逻辑就是判断当前的值是否被更新过,是否等于current,如果等于就说明没有更新过然后将当前的值更新为next,如果不等于则返回false进入循环,直到更新成功为止。 还有其中的get()方法也很关键,返回的是当前的值,当前值用了volatile关键词修饰,保证了内存可见性。 private volatile int value; 2、可见性 可见性就是指当一个线程修改了线程共享变量的值,其它线程能够立即得知这个修改。 现代计算机中,由于CPU直接从主内存中读取数据的效率不高,所以都会对应的CPU高速缓存,先将主内存中的数据读取到缓存中,线程修改数据之后首先更新到缓存,之后才会更新到主内存。如果此时还没有将数据更新到主内存其他的线程此时来读取就是修改之前的数据。 如上图所示。 volatile关键字就是用于保证内存可见性,当线程A更新了 volatile 修饰的变量时,它会立即刷新到主线程,并且将其余缓存中该变量的值清空,导致其余线程只能去主内存读取最新值。 使用volatile关键词修饰的变量每次读取都会得到最新的数据,不管哪个线程对这个变量的修改都会立即刷新到主内存。 synchronize和加锁也能能保证可见性,实现原理就是在释放锁之前其余线程是访问不到这个共享变量的。但是和volatile相比开销较大。 3、顺序性 Java内存模型中的程序天然有序性可以总结为一句话:如果在本线程内观察,所有操作都是有序的;如果在一个线程中观察另一个线程,所有操作都是无序的。前半句是指“线程内表现为串行语义”,后半句是指“指令重排序”现象和“工作内存中主内存同步延迟”现象。 正常情况下的执行顺序应该是1>>2>>3。但是有时JVM为了提高整体的效率会进行指令重排导致执行的顺序可能是2>>1>>3。但是JVM也不能是什么都进行重排,是在保证最终结果和代码顺序执行结果一致的情况下才可能进行重排。 重排在单线程中不会出现问题,但在多线程中会出现数据不一致的问题。 Java 中可以使用volatile来保证顺序性, 和 lock也可以来保证有序性,和保证原子性的方式一样,通过同一段时间只能一个线程访问来实现的。 除了通过volatile关键字显式的保证顺序之外,JVM还通过happen-before原则来隐式的保证顺序性。 其中有一条就是适用于volatile关键字的,针对于volatile关键字的写操作肯定是在读操作之前,也就是说读取的值肯定是最新的。 volatile 的应用 双重检查锁的单例模式 可以用volatile实现一个双重检查锁的单例模式: 这里的volatile关键字主要是为了防止指令重排。 如果不用volatile,singleton = new Singleton();,这段代码其实是分为三步: 分配内存空间。(1) 初始化对象。(2) 将singleton对象指向分配的内存地址。(3) 加上volatile是为了让以上的三步操作顺序执行,反之有可能第二步在第三步之前被执行就有可能某个线程拿到的单例对象是还没有初始化的,以致于报错。 控制停止线程的标记 这里如果没有用 volatile 来修饰 flag ,就有可能其中一个线程调用了stop()方法修改了 flag 的值并不会立即刷新到主内存中,导致这个循环并不会立即停止。 这里主要利用的是volatile的内存可见性。 总结一下: volatile关键字只能保证可见性,顺序性,不能保证原子性。 欢迎工作一到五年的Java工程师朋友们加入Java架构开发:468947140 点击链接加入群聊【Java-BATJ企业级资深架构】:https://jq.qq.com/?_wv=1027&k=5zMN6JB 本群提供免费的学习指导 架构资料 以及免费的解答 不懂得问题都可以在本群提出来 之后还会有职业生涯规划以及面试指导 如果觉得本文还可以,欢迎大家《关注》,算是对笔者的支持

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册