java高并发----个人学习理解汇总记录
1.首先,需要理解几个概念
1.同步(Synchronous):同步方法调用一旦开始,调用者必须等到前面的方法调用返回后,才能继续后续的行为,依次直到完成所有。
2.异步(Asynchronous):异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者就可以继续后续的操作。异步方法通常会在另外一个线程中“真实”地执行。整个过程,不会阻碍当前调用者的工作。
3.并发(Concurrency):在一个时间段内,多件事情在这个时间段内交替执行。比如说:有两个队列,进入同一个入口,交替进入。
4.并行(Parallelism):多件事情在同一个时刻同事发生。比如说:有两个队列,分别进如两个入口。互不干扰。
注意:实际上,如果系统内只有一个CPU,而使用多进程或者多线程任务,那么真实环境中这些任务不可能是真实并行的,毕竟一个CPU一次只能执行一条指令,在这种情况下多进程或者多线程就是并发的,而不是并行的(操作系统会不停地切换多任务)。真实的并行也只可能出现在拥有多个CPU的系统中(比如多核CPU)。
5.临界区:临界区用来表示一种公共资源或者说共享数据,可以被多个线程使用,但是每一次只能有一个线程使用它,一旦临界区资源被占用,其他线程要想使用这个资源就必须等待。
6.阻塞(Blocking):一个线程占用了临界区资源,其他的线程就必须在这个临界区中等待,会导致线程挂起,这种情况就是阻塞。
7.非阻塞(Non-Blocking):没有一个线程可以妨碍其他线程执行,所有的线程都会尝试不断向前执行。
8.死锁(Deadlock):几个线程都不释放资源,也得不到自己所需要的资源,导致线程都没办法继续进行下去。
注意:可以通过jstack命令进行查看,其中所需要的pid可以通过命令行获取到,也可以通过jdk提供的jconsole.exe工具直接查看当前线程的pid。不懂自行百度
9.饥饿(Starvation):指某一个或者多个线程因为种种原因无法获得所要的资源,导致一直无法执行。比如它的优先级可能太低,而高优先级的线程不断抢占它需要的资源,导致低优先级线程无法工作
10.活锁(Livelock):比如两个线程都秉承着“谦让”的原则,主动将资源释放给他人使用,可能会导致资源不断地在两个线程间跳动,而没有一个线程可以同时拿到所有资源正常执行。这种情况就是活锁
总结:这里的概念学习起来比较枯燥,多进行理解,孰能生巧。
2.并发级别概念
根据控制并发的策略,我们可以把并发的级别分为阻塞、无饥饿、无障碍、无锁、无等待几种。
1.阻塞:一个线程是阻塞的,那么在其他线程释放资源之前,当前线程无法继续执行。当我们使用synchronized关键字或者重入锁时,我们得到的就是阻塞的线程。
2.无饥饿:线程之间是有优先级的,那么线程调度的时候总是会倾向于先满足高优先级的线程。其中分为非公平锁与公平锁两种情况。公平锁不管新来的线程优先级多高,要想获得资源,就必须乖乖排队,这样所有的线程都有机会执行
3.无障碍:无障碍是一种最弱的非阻塞调度。两个线程如果无障碍地执行,那么不会因为临界区的问题导致一方被挂起。大家一起修改共享数据,把数据改坏了怎么办呢?对于无障碍的线程来说,一旦检测到这种情况,它就会立即对自己所做的修改进行回滚,确保数据安全。
4.无锁:无锁的并行都是无障碍的。在无锁的情况下,所有的线程都能尝试对临界区进行访问,但不同的是,无锁的并发保证必然有一个线程能够在有限步内完成操作离开临界区。
5.无等待:无锁只要求有一个线程可以在有限步内完成操作,而无等待则在无锁的基础上更进一步扩展。它要求所有线程都必须在有限步内完成,这样不会引起饥饿问题。如果限制这个步骤的上限,还可以进一步分解为有界无等待和线程数无关的无等待等几种,他们之间的区别只是对循环次数的限制不同
3.并行的两个重要定律
为什么要使用并行程序的问题前面已经进行了简单的探讨。总的来说,最重要的应该是处于两个目的。
第一,为了获得更好的性能;
第二,由于业务模型的需要,确实需要多个执行实体。
在这里,更加关注第一种情况,也就是有关性能的问题。将串行程序改造为并发程序,一般来说可以提高程序的整体性能,但是究竟能提高多少,甚至说究竟是否真的可以提高,还是一个需要研究的问题。目前,主要有两个定律对这个问题进行解答,一个是Amdahl定律,另外一个是Gustafson定律。
关于这两个定律,不是很理解,研究更深入客自行百度,总的来说,提升性能的方法:想办法提升系统并行的比例,同时增加CPU数量。
4.JMM(java内存模型)相关的一些概念
JMM关键技术点都是围绕着多线程的原子性、可见性、有序性来建立的
1.原子性:是指操作是不可分的,要么全部一起执行,要么不执行。在java中,其表现在对于共享变量的某些操作,是不可分的,必须连续的完成。比如a++,在操作a++的过程中,其他线程不会改变a的值。
注意:java中实现原子操作的方法大致有2种:锁机制、无锁CAS机制
2.可见性:可见性是指一个线程对共享变量的修改,对于另一个线程来说是否是可以看到的。比如:线程A对共享变量的修改要被线程B及时看到的话,需要进过以下步骤:1.线程A在自己的工作内存中修改变量之后,需要将变量的值刷新到主内存中 2.线程B要把主内存中变量的值更新到工作内存中
注意:可以使用volatile、synchronized、锁来实现
3.有序性:有序性指的是程序按照代码的先后顺序执行。为了性能优化,编译器和处理器会进行指令冲排序,有时候会改变程序语句的先后顺序
5.理解进程和线程
1.进程:我们经常使用windows系统,经常会看见.exe后缀的文件,双击这个.exe文件的时候,这个文件中的指令就会被系统加载,那么我们就能得到一个关于这个.exe程序的进程。
2.线程:线程是轻量级的进程,是程序执行的最小单元,使用多线程而不是多进程去进行并发程序的设计,是因为线程间的切换和调度的成本远远小于进程,线程的所有状态在java.lang.Thread中的State枚举中有定义:
New:表示刚刚创建的线程,这种线程还没有开始执行
RUNNABLE:运行状态,线程的start()方法调用后,线程会处于这种状态
BLOCKED:阻塞状态。当线程在执行的过程中遇到了synchronized同步块,但这个同步块被其他线程已获取还未释放时,当前线程将进入阻塞状态,会暂停执行,直到获取到锁。当线程获取到锁之后,又会进入到运行状态(RUNNABLE)
WAITING:等待状态。和TIMEWAITING都表示等待状态,区别是WAITING会进入一个无时间限制的等,而TIMEWAITING会进入一个有限的时间等待,那么等待的线程究竟在等什么呢?一般来说,WAITING的线程正式在等待一些特殊的事件,比如,通过wait()方法等待的线程在等待notify()方法,而通过join()方法等待的线程则会等待目标线程的终止。一旦等到期望的事件,线程就会再次进入RUNNABLE运行状态。
TERMINATED:表示结束状态,线程执行完毕之后进入结束状态。
注意:从NEW状态出发后,线程不能在回到NEW状态,同理,处理TERMINATED状态的线程也不能在回到RUNNABLE状态
个人理解:单个CPU一次只能运行一个任务,任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。其中,一个进程可以包括多个线程,一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。需要注意的是:一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存
注意:以上全部都是基本概念的理解,对于高并发的代码技巧掌握,不要急于求成,更多的是要着重于每一个基础知识点的逐步积累,万丈高楼平地起,一起加油骚年们。
java高并发----个人学习理解汇总记录的更多相关文章
- Java高并发程序设计学习笔记(十一):Jetty分析
转自:https://blog.csdn.net/dataiyangu/article/details/87894253 new Server()初始化线程池QueuedThreadPoolexecu ...
- Java高并发程序设计学习笔记(十):并发调试和JDK8新特性
转自:https://blog.csdn.net/dataiyangu/article/details/87631574 多线程调试的方法使用Eclipse进行多线程调试线程dump及分析分析死锁案例 ...
- Java高并发程序设计学习笔记(七):并行设计模式
转自:https://blog.csdn.net/dataiyangu/article/details/87123586 什么是设计模式架构模式设计模式代码模式(成例 Idiom)单例模式普通单例假如 ...
- Java高并发程序设计学习笔记(二):多线程基础
转自:https://blog.csdn.net/dataiyangu/article/details/86226835# 什么是线程?线程的基本操作线程的基本操作新建线程调用run的一种方式调用ru ...
- 慕课网Java高并发秒杀学习
课程地址:http://www.imooc.com/learn/587 一个很好:spring,springMVC,mybatis,bootstrap,jQuery,mysql,Restful学习案例 ...
- Java高并发程序设计学习笔记(九):锁的优化和注意事项
转自:https://blog.csdn.net/dataiyangu/article/details/87612028 锁优化的思路和方法减少锁持有时间减小锁粒度锁分离锁粗化举个栗子举个栗子锁消除虚 ...
- Java高并发程序设计学习笔记(六):JDK并发包(线程池的基本使用、ForkJoin)
转自:https://blog.csdn.net/dataiyangu/article/details/86573222 1. 线程池的基本使用1.1. 为什么需要线程池1.2. JDK为我们提供了哪 ...
- Java高并发程序设计学习笔记(四):无锁
转自:https://blog.csdn.net/dataiyangu/article/details/86440836#1__3 1. 无锁类的原理详解简介:1.1. CAS1.2. CPU指令2. ...
- Java高并发程序设计学习笔记(三):Java内存模型和线程安全
转自:https://blog.csdn.net/dataiyangu/article/details/86412704 原子性有序性可见性– 编译器优化– 硬件优化(如写吸收,批操作)Java虚拟机 ...
随机推荐
- Ajax发送请求的四个步骤
1.创建XMLHttpRequest let xhr=new XMLHttpRequest; 2.连接服务器 xhr.open("get","goods.json&quo ...
- Spring Boot 利用 nginx 实现生产环境的伪热更新
当我们在服务器部署Java程序,特别是使用了 Spring Boot 生成单一 Jar 文件部署的时候,单一文件为我们开发单来的极大的便利性,保障程序的完整性.但同时对我们修改程序中的任何一处都带来重 ...
- java生成随机验证码图片
import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; i ...
- HMAC256 Token
依赖包: <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</arti ...
- asp.net配置全局应用程序类 巧妙达到定时生成静态页面
//在项目里添加一个"全局应用程序类(Global Application Class)",在里面写这样的代码: public class Global : System.Web. ...
- ogeek线下赛web分析1-python-web
1.python from flask import Flask, request, render_template,send_from_directory, make_response from A ...
- 04 (H5*) Vue第四天
目录: 1:父组件向子组件传值,通过属性绑定的方式. 2:父组件向子组件传方法,通过事件绑定的方式 . 3:通过ref来获取Dom元素 1:父组件向子组件传值,通过属性绑定的方式 1.1:父组件声明数 ...
- seo搜索引擎的优化方法
现在互联网的入口,一般都是被搜索引擎霸占.所以我们要想让别人搜索时,优先看到我们的网站.有两种方法: 1.竞价排名.这是需要钱的,给的钱越多,排名越靠前.参考某度.. 2.不想花钱,就使用seo搜索引 ...
- mysql隔离级别的测试
mysql提供四种隔离级别,以下分别对四种隔离级别进行测试,更加直观清晰的了解.具体的隔离级别以及其他相关介绍见https://www.cnblogs.com/eric-fang/p/11052304 ...
- 微信小程序中的tabBar设置
我们先来看一份图,这个设置在官方文档中已经写得很清楚了,我只是做一个总结 注:我写注释是为了方便说明,在小程序中的json文件中是不能用注释的 这个tabBar属于全局属性,因此就在全局配置文件app ...