线程

线程和进程的区别

て烟熏妆下的殇ゞ 提交于 2020-03-24 06:42:50
一个程序至少有一个进程,而一个进程至少有一个线程。进程在执行的过程拥有独立的内存单元,而多个线程共享该内存,极大的提高了程序的执行效率。 进程与线程在执行时候的区别:每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. 一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。 关于进程和线程的介绍 1、进程(process)是一块包含了某些资源的内存区域。操作系统利用进程把它的工作划分为一些功能单元。 进程中所包含的一个或多个执行单元称为线程(thread)。进程还拥有一个私有的虚拟地址空间,该空间仅能被它所包含的线程访问。 当运行.NET程序时

深入理解Synchronized

拥有回忆 提交于 2020-03-23 22:13:08
3 月,跳不动了?>>> 目前在Java中存在两种锁机制:synchronized和Lock,Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug Lea。本文并不比较synchronized与Lock孰优孰劣,只是介绍二者的实现原理。 数据同步需要依赖锁,那锁的同步又依赖谁?synchronized给出的答案是在软件层面依赖JVM,而Lock给出的方案是在硬件层面依赖特殊的CPU指令,大家可能会进一步追问:JVM底层又是如何实现synchronized的? 本文所指说的JVM是指Hotspot的6u23版本,下面首先介绍synchronized的实现: synrhronized关键字简洁、清晰、语义明确,因此即使有了Lock接口,使用的还是非常广泛。其应用层的语义是可以把任何一个非null对象作为"锁",当synchronized作用在方法上时,锁住的便是对象实例(this);当作用在静态方法时锁住的便是对象对应的Class实例,因为Class数据存在于永久带,因此静态方法锁相当于该类的一个全局锁;当synchronized作用于某一个对象实例时,锁住的便是对应的代码块。在HotSpot JVM实现中,锁有个专门的名字:对象监视器。 1. 线程状态及状态转换 当多个线程同时请求某个对象监视器时,对象监视器会设置几种状态用来区分请求的线程:

synchronized实现原理

一个人想着一个人 提交于 2020-03-23 22:12:53
3 月,跳不动了?>>> 目前在Java中存在两种锁机制:synchronized和Lock。数据同步需要依赖锁,那锁时如何实现的呢,synchronized给出的答案是软件层面依赖JVM,而Lock给出的方案是在硬件层面依赖特殊的CPU指令。 下面先介绍synchronized的实现: synchronized 是关键字,即使有了Lock接口(Lock能够实现synchronized能够实现的所有功能),使用的还是非常广泛。其应用层的语义是可以把任何一个非nul对象作为锁,当synchronized作用在方法上时,锁住的对象是实例对象(this);当作用在静态方法时锁住的对象时对象对应的Class实例,因为Class数据存在于永久带,因此静态方法锁相当于类的一个全局锁;当synchronized作用于某一个对象实例时,锁住的便是对应的代码块。在JVM实现中,所有一个专门的名字:对象监视器 线程状态与状态的转换 当多个线程同时请求某个对象监视器时,对象监视器会设置几种状态来区分请求的线程 Contention List:所有请求锁的线程将被首先放置到竞争队列。Contention List是一个虚拟队列,原因在于Contention List是一个由Node及next指针逻辑构成,并不存在一个Queue的数据结构。ContentionList是一个后进先出(LIFO)队列。

Java多线程并发09——如何实现线程间与线程内数据共享

一个人想着一个人 提交于 2020-03-23 20:42:20
本文将为各位带来 Java 阻塞队列相关只是。关注我的公众号「Java面典」了解更多 Java 相关知识点。 线程间数据共享 Java 里面进行多线程通信的主要方式就是共享内存的方式,共享内存主要的关注点有两个:可见性和有序性原子性。Java 内存模型(JMM)解决了可见性和有序性的问题,而锁解决了原子性的问题,理想情况下我们希望做到“同步”和“互斥”。有以下常规实现方法: 将数据抽象成一个类 将数据抽象成一个类,并将对这个数据的操作作为这个类的方法,这么设计可以和容易做到同步,只要在方法上加”synchronized“。 public class MyData { private int j = 0; public synchronized void add() { j++; System.out.println("线程" + Thread.currentThread().getName() + "j 为:" + j); } public synchronized void dec() { j--; System.out.println("线程" + Thread.currentThread().getName() + "j 为:" + j); } public int getData() { return j; } } public class AddRunnable

nested exception is java.lang.StackOverflowError解析

喜你入骨 提交于 2020-03-23 20:41:14
背景介绍: 项目是微服务的,使用docker容器,使用jenkins部署。测试环境有个公共服务一直以来都能正常发布,突然有一天不行了,经常发布失败,然后多发布几次就好了。 报错如下: 是栈溢出了,一般是新代码有死循环会出现。但是本地启动没问题并且环境上多发几次也能成功,说明没有死循环,肯定是其他原因。 分析问题: Java运行时数据区分5部分: 从报错上来看是虚拟机栈溢出。 虚拟机栈是属于线程私有的,每个线程都会有一个虚拟机栈,随线程的创建而创建,消失而消失。它由一个个的栈帧组成,线程每次调用一个方法,就会有一个栈帧生成,并压栈。方法调用完之后,栈帧则出栈。当栈的深度不够,即栈的大小不足以放下所有的栈帧的时候,就会抛栈溢出的异常。 问题明确了,是栈的大小不够。 解决问题: 要把栈大小设置的大一点,要设置的大一点首先要知道目前是多大。项目未对虚拟机栈的大小作设定,也就是说目前的大小是默认值。 JDK5之后每个栈大小是1M,之前是256k。我们用的是JDK8,那么大小就是1M。要把栈大小设成大于1M的值。但是又不能设置太大,因为如果单个线程栈太大,就会限制最大线程数量。 项目没有高并发的情况,所以就先设置成2M。设置方法,在JVM启动参数里面加上 -Xss2m 。 问题解决,再也没出现过问题。 来源: https://www.cnblogs.com/sam-uncle/p

Java进程故障排查思路及步骤

荒凉一梦 提交于 2020-03-23 17:49:44
一、故障现象 Java进程出现问题,通常表现出如下现象: 1.CPU使用率持续极高/低 2.内存占用持续极高,甚至出现OOM(例如:进程正常运行一段时间之后突然不再响应请求,但是进程依然存在) 3.Web应用响应时间很长/超时,甚至不响应直接出现502(使用nginx作为反向代理) 响应时间长、超时,甚至不响应,这是最直观的表现;而CPU使用率极高或极低,频繁出现Full GC甚至OOM,需要借助系统日志或者监控辅助发现。 二、原因分析 响应时间长、超时,甚至不响应,这是一个综合性的故障结果,可能并不单纯是应用程序本身的问题。 首先,需要排查网络连通性是否正常; 其次,如果后端还接了数据存储系统,除了排查应用程序本身的问题之外,还需要排查应用所依赖的第三方组件是否出现了性能瓶颈,这通常可以从应用程序日志中看到错误信息。 在直观的故障表象背后是对应的系统指标异常,排查思路如下。 CPU使用率极低 通常是线程Hang住了,或者是出现了死锁,通过线程堆栈日志可以进行定位。 CPU使用率持续极高 先使用jstack命令查看堆栈信息,结合线程堆栈信息分析可能的原因: 业务代码很忙,甚至出现了死循环,这个从线程堆栈日志中可以 定位到具体的代码块 频繁出现GC,特别是Full GC,从gc日志中可以得知 TCP连接数很高,这通常是高并发导致的 系统日志输出很频繁也会导致CPU占用很高

【Go专家编程】调度模型

社会主义新天地 提交于 2020-03-23 17:47:41
3 月,跳不动了?>>> 线程模型 线程可分为用户线程和内核线程,用户线程由用户创建、同步和销毁,内核线程则由内核来管理。 根据用户线程管理方式的不同,分为三种线程模型。 一种是N:1模型,即N个用户线程运行在1个内核线程中,优点是用户线程上下文切换快,缺点是无法充分利用CPU多核的算力。 另一种是1:1模型,即每个用户线程对应一个内核线程,优点是充分利用CPU,缺点是线程上下文切换较慢。 Go实现的是M:N模型,即前两种模型的组合,M个用户线程(协程)运行在N个线程中,优点是充分利用CPU的算力且协程上下文切换快,缺点则是该模型的调度算法较为复杂。 Go调度器模型 Go协程调度模型中包含三个关键实体,Machine(简称M)、Processor(简称P)和Goroutine(简称G)。 M(Machine):工作线程,它由操作系统调度; P(Processor):处理器(Go定义的一个摡念,不是指CPU),包含运行Go代码的必要资源,也有调度goroutine的能力。 G(Goroutine): 即Go协程,每个go关键字都会创建一个协程。 M必须持有P才可以执行代码,跟系统中的其他线程一样,M也会被系统调用阻塞。 来源: oschina 链接: https://my.oschina.net/renhc/blog/3209215

多线程面试总结

空扰寡人 提交于 2020-03-23 16:48:09
操作系统的设计,因此可以归结为三点: (1)以多进程形式,允许多个任务同时运行; (2)以多线程形式,允许单个任务分成不同的部分运行; (3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。 2. 线程与进程的区别? 程序: 完成某种功能的一段代码。静态概念。 任务: 程序完成的一个活动。既可以是一个进程,也可以是一个线程。 进程: 程序的一次执行过程。一个独立的进程在内存中有自己的数据空间和代码空间。它所拥有的数据变量属于它自己。 线程: 线程是进程的一个执行序列。同一个进程创建的多个线程可以共享进程的一些资源,如全局变量,同时,多个线程可以有自己的栈空间,线程的局部变量只属于这个线程。 线程可以有自己的堆栈和局部变量,但线程没有单独的地址空间,因此一个线程死掉就等于整个进程死掉,所以线程的健壮性不如进程。但进程切换时,系统开销大,因此 资源利用率低。 对于一些要求同时运行且要共享资源的并发操作,只能用线程,而不能用进程。 总结:1. 一个线程只能同时属于一个进程,一个进程可以有多个线程,且至少有一个线程。 2. 同一进程的所有线程共享进程的所有资源。有些资源的访问需要线程之间互斥访问。 3. 真正在处理机上运行的是线程,而不是进程。 4. 同步问题: 不同进程的线程之间利用消息通信的方式实现同步。 线程与进程的区别? 1、

死磕 java集合之SynchronousQueue源码分析

隐身守侯 提交于 2020-03-23 16:23:15
问题 (1)SynchronousQueue的实现方式? (2)SynchronousQueue真的是无缓冲的吗? (3)SynchronousQueue在高并发情景下会有什么问题? 简介 SynchronousQueue是java并发包下无缓冲阻塞队列,它用来在两个线程之间移交元素,但是它有个很大的问题,你知道是什么吗?请看下面的分析。 源码分析 主要属性 // CPU的数量 static final int NCPUS = Runtime.getRuntime().availableProcessors(); // 有超时的情况自旋多少次,当CPU数量小于2的时候不自旋 static final int maxTimedSpins = (NCPUS < 2) ? 0 : 32; // 没有超时的情况自旋多少次 static final int maxUntimedSpins = maxTimedSpins * 16; // 针对有超时的情况,自旋了多少次后,如果剩余时间大于1000纳秒就使用带时间的LockSupport.parkNanos()这个方法 static final long spinForTimeoutThreshold = 1000L; // 传输器,即两个线程交换元素使用的东西 private transient volatile Transferer<E>

[C#]从两个例子理解async/await

一笑奈何 提交于 2020-03-23 16:17:39
1 例子1 输出的结果为: 可以看出执行的结果为:A——D——B——C——E. 我们再看下一个例子 (注意,我们把代码中D和E的位置交换) 2 例子2 结果: 结果为:A——B——C——E——D 3 理解 Async方式,使用Async标记 Test 为异步方法,用Await标记 Task 表示方法内需要耗时的操作。主线程碰到await时会立即返回,继续以非阻塞形式执行主线程下面的逻辑。当await耗时操作完成时,继续执行 Test 中下面的逻辑。 因此我们回头看例子1执行顺序: 先执行Test方法,输出A,碰到await,进入之后立即返回执行主线程逻辑,这里也就是输出D,但是下面输出E需要Test方法返回的结果,所以这里主线程被阻塞了,然后等待异步耗时方法中的B输出之后,继续往下执行,输出C,最后获得了异步方法的结果,再输出E 再看例子2执行顺序: 先执行Test方法,输出A,碰到await,进入后立即执行返回主线程执行,但是下面一行代码又需要Test方法的返回值,所以这里被阻塞住了,等待异步方法中执行完输出B,在继续往下输出C,返回结果,之后再往下输出E,然后输出D 也就是说:主线程一碰到await就返回去做自己的事情(直到await执行完成),等await完成之后再继续执行await下面的方法(除非主线程下面需要使用到异步方法的返回值,否则不会阻塞) 个人理解,欢迎指正!