读《Java并发编程的艺术》(一)
离开博客园很久了,自从找到工作,到现在基本没有再写过博客了。在大学培养起来的写博客的习惯在慢慢的消失殆尽,感觉汗颜。所以现在要开始重新培养起这个习惯,定期写博客不仅是对自己学习知识的一种沉淀,更是在督促自己要不断的学习,不断的进步。
最近在进一步学习Java并发编程,不言而喻,这部分内容是很重要的。现在就以《并发编程的艺术》一书为主导线,开始新一轮的学习。
进程和线程
进程是一个应用程序在处理机上的一次执行过程,线程是进程的最小基本单位(个人理解)。一个进程可以包含多个线程。
上下文切换
我们都知道,即使是单核处理器也支持多线程,CPU通过时间片分配算法来给每个线程分配时间让线程得以执行,因为时间片非常短,所以在用户角度来讲,会感觉多个线程是在同时执行。那什么是上下文切换呢?举个例子,当线程A执行到某一步时,此时CPU将时间让给了线程B进行执行,那么在进行切换的时候,系统一定要保存此时此刻线程A所执行任务的状态,比如执行到哪里、运行时的参数等,那么当下一次CPU将时间让给线程A进行执行时,才能正确的切换到A,并继续执行下去。所以任务从保存到再加载的过程就是一次上下文切换。
虽然上下文切换可以让我们觉得可以“同时”做很多事,但是上下文切换也是需要系统开销的。在《Java并发编程的艺术》中,作者举例演示了串行和并发执行累加操作,在结果中可以看得出,累加操作不同的次数会对不同的结果,所消耗的时间也有差别的。如果累加操作的次数没有超过百万次,那么串行执行结果消耗的时间会比并行执行的时间要少。所以在有些情况下我们需要尽可能的减少上下文切换的次数,使用的方法有:无锁并发编程,CAS算法,使用最少线程和使用协程。(这里笔者也只知道有这几种方法,至于具体如何使用以及在何种场景下使用还未深入研究)。
volatile与synchronized
volatile
volatile是轻量级的synchronized,它保证了在多处理器开发中,共享变量的可见性,并且volatile不会引起上下文切换和调度。可见性的意思是当一个线程修改了某个变量的值,另外一个线程可以读到这个变量修改后的值,如果一个变量被volatile修饰,那么Java内存模型确保所有线程看到这个变量的值是一致的。
synchronized
Java中每一个对象都可以作为锁,具体表现为:
- 对于普通的同步方法,锁是当前实例对象
- 对于静态的同步方法,锁是当前类的Class对象
- 对于同步方法块,锁是synchronized括号里配置的对象
当一个线程访问同步代码块时,必须要先得到锁,退出或抛出异常时,必须释放锁。对于上述三种情况,表现形式为:
/**
* 普通同步方法,锁是当前实例对象
*/
public synchronized void test1(){
//TODO something
} /**
* 静态同步方法,锁是当前类的Class对象
*/
public static synchronized void test2(){
//TODO something
} /**
* 同步方法块,锁是synchronized括号中的对象,这里是a
*/
public void test3(Integer a){
synchronized (a){
//TODO something
}
}
Java内存模型
Java中所有实例域、静态域和数组元素都存储在堆内存中,堆内存在线程之间共享。
Java线程之间的通信由Java内存模型(JMM)控制。JMM定义了线程和主内存的关系:线程之前的共享变量存储在主内存中,每个线程都有一个私有的本地内存(也叫工作内存),本地内存中存储了该线程读写共享变量的副本。本地内存是JMM的抽象概念,不真实存在,包涵了缓存,写缓冲区,寄存器以及其他硬件和编译器优化。Java内存模型结构图:
从上图可以看出,线程A要与线程B进行通信的话,必须要经过两个步骤:
- 线程A把本地内存A中更新过的共享变量刷新要主内存中去,
- 线程B到主内存中获取更新之后的共享变量。
如下图:
重排序
重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。
数据依赖性
定义:如果两个操作同时访问一个变量,且这两个操作中有一个为写操作。此时这两个操作之间就存在数据依赖性。
编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。
as-if-serial语义
语义:不管怎么重排序,单线程程序的执行结果不能被改变。编译器,runtime和处理器都必须遵守as-if-serial语义。
为了遵守as-if-serial语义,编译器和处理器不会对存在数据依赖关系的操作进行重排序,但是如果操作之间不存在数据依赖关系,那么就有可能被进行重排序。例如:
double pi = 3.14 ; //A
double r = 1.0 ; //B
double area = pi * r *r ; //C
上面代码中,C依赖A,C依赖B,所以编译器不会重排序将C排在A,B之前。但是A,B之间没有依赖,所以可能被进行重排序,最终的执行顺序有两种:
A->B->C;
B->A->C;
这两种执行顺序对最终结果不会造成影响。
因为存在重排序,所以单线程程序不一定按照程序的顺序来执行。
该文主要讲述了一些偏概念的东西,先有一些印象,后续会以代码示例的形式进行全面的复习。
读《Java并发编程的艺术》(一)的更多相关文章
- 那些年读过的书《Java并发编程实战》和《Java并发编程的艺术》三、任务执行框架—Executor框架小结
<Java并发编程实战>和<Java并发编程的艺术> Executor框架小结 1.在线程中如何执行任务 (1)任务执行目标: 在正常负载情况下,服务器应用 ...
- 读《Java并发编程的艺术》学习笔记(一)
接下来一个系列,是关于<Java并发编程的艺术>这本书的读书笔记以及相关知识点,主要是为了方便日后多次复习和防止忘记.废话不多说,直接步入主题: 第1章 并发编程的挑战 并发编程的目的是 ...
- Java并发编程的艺术读书笔记(2)-并发编程模型
title: Java并发编程的艺术读书笔记(2)-并发编程模型 date: 2017-05-05 23:37:20 tags: ['多线程','并发'] categories: 读书笔记 --- 1 ...
- Java并发编程的艺术(六)——线程间的通信
多条线程之间有时需要数据交互,下面介绍五种线程间数据交互的方式,他们的使用场景各有不同. 1. volatile.synchronized关键字 PS:关于volatile的详细介绍请移步至:Java ...
- Java并发编程的艺术(三)——volatile
1. 并发编程的两个关键问题 并发是让多个线程同时执行,若线程之间是独立的,那并发实现起来很简单,各自执行各自的就行:但往往多条线程之间需要共享数据,此时在并发编程过程中就不可避免要考虑两个问题:通信 ...
- 《Java并发编程的艺术》留给自己以后看的笔记
<Java并发编程的艺术>这本书特别好,和<深入了解JAVA虚拟机>有一拼,建议做java的都看看,下面全部都是复制书中的部分内容,主要目的是做个笔记,方便以后遇到问题能找到. ...
- 读书笔记之《Java 并发编程的艺术》
一.多线程语义 即使是单核处理器也支持多线程执行代码,CPU 通过给每个线程分配 CPU 时间片来执行任务,当前任务执行一个时间片后会切换到下一个任务,所以 CPU 通过不停的切换线程执行. 并发执行 ...
- 《Java并发编程的艺术》读书笔记:二、Java并发机制的底层实现原理
二.Java并发机制底层实现原理 这里是我的<Java并发编程的艺术>读书笔记的第二篇,对前文有兴趣的朋友可以去这里看第一篇:一.并发编程的目的与挑战 有兴趣讨论的朋友可以给我留言! 1. ...
- Java并发编程的艺术读书笔记(1)-并发编程的挑战
title: Java并发编程的艺术读书笔记(1)-并发编程的挑战 date: 2017-05-03 23:28:45 tags: ['多线程','并发'] categories: 读书笔记 --- ...
随机推荐
- Unity 3D Framework Designing(3)——构建View和ViewModel的生命周期
> 对于一个View而言,本质上是一个MonoBehaviour.它本身就具备生命周期这个概念,比如,Awake,Start,Update,OnDestory等.这些是非常好的方法,可以让开发者 ...
- Sublime Text 3下载-汉化-插件配置
Sublime Text 3下载 不用说是上官方下载地址:http://www.sublimetext.com/3 Sublime Text 3 免费使用方法 Sublime Text 2的时候还有一 ...
- PHP开发人员对JAVA的WEB开发入门(初版-已废弃)
最近准备对其他部门PHP开发的童鞋做一个对JAVA的培训.知己知彼,百战不殆,我要先了解点PHP,才能确认他们的基础,达到好的授课效果. PHP(原始为Personal Home Page的缩写,后正 ...
- 车大棒浅谈jQuery源码(二)
前言 本来只是一个自己学习jQuery笔记的简单分享,没想到获得这么多人赏识.我自己也是傻呵呵的一脸迷茫,感觉到受宠若惊. 不过还是有人向批判我的文章说,这是基本知识点,完全跟jQuery源码沾不上边 ...
- 【Spring】BeanFactory解析bean详解
在该文中来讲讲Spring框架中BeanFactory解析bean的过程,该文之前在小编原文中有发表过,要看原文的可以直接点击原文查看,先来看一个在Spring中一个基本的bean定义与使用. pac ...
- POPTEST老李分享DOM解析XML之java
POPTEST老李分享DOM解析XML之java Java提供了两种XML解析器:树型解释器DOM(Document Object Model,文档对象模型),和流机制解析器SAX(Simple ...
- windows系统System32中各种实用的工具
工具类 这些工具可以直接打开运行 输入名字就可以调出来了 我还会上传一个java程序,运行后会显示一个界面,直接调用这些工具 1.SnippingTool.exe 截图 2.calc.exe ...
- sqlldr用法
SQL*LOADER是ORACLE的数据加载工具,通常用来将操作系统文件迁移到ORACLE数据库中.SQL*LOADER是大型数据仓库选择使用的加载方法,因为它提供了最快速的途径(DIRECT,PAR ...
- 基于MVC和Bootstrap的权限框架解决方案 二.添加增删改查按钮
上一期我们已经搭建了框架并且加入了列表的显示, 本期我们来加入增删改查按钮 整体效果如下 HTML部分,在HTML中找到中意的按钮按查看元素,复制HTML代码放入工程中 <a class=&qu ...
- [UWP]了解模板化控件(5):VisualState
1. 功能需求 使用TemplatePart实现上篇文章的两个需求(Header为空时隐藏HeaderContentPresenter,鼠标没有放在控件上时HeaderContentPresent半透 ...