进程是资源分配的最小单位,线程是CPU调度的最小单位java
总结:c++
实现方式有三种算法
实现的方式主要有三种:编程
锁池EntryList:假设线程A已经得到了某个对象(不是类)的锁,而其余线程B,C想要调用这个对象的某个synchronized方法(或者块),因为B,C线程在进入对象的synchronized方法以前必须得到该对象锁的拥有权,而恰巧该对象的锁恰好被线程A所占用,此时B,C线程就会被阻塞,进入一个地方去等待锁的释放,这个地方就是锁池。数组
等待池WaitSet:假设线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁,同时线程A就进入到了该对象的等待池中,进入到等待池中的线程不会去竞争该对象的锁。缓存
当调用Thread.yeild()函数时,会给线程调度器一个当前线程愿意让出CPU使用的暗示,可是线程调度器可能会忽略这个暗示。并不会让出当前线程的锁。安全
join方法可使得一个线程在另外一个线程结束后再执行。当前线程将阻塞直到这个线程实例完成了再执行。多线程
已经被抛弃的方法:并发
目前使用的方法:app
线程安全出现的缘由:
解决线程安全的根本办法:同一时刻有且只有一个线程在操做共享数据,其余线程必须等到该线程处理完数据以后再对共享数据进行操做,引入了互斥锁
互斥锁的特性:
根据获取的锁分类:
synchronized底层实现原理:
锁的内存语义:
synchronized的四种状态:
AQS提供了一种实现阻塞锁和一系列依赖FIFO等待队列的同步器的框架,AbstractQueuedSynchronizer中对state的操做是原子的,且不能被继承。全部的同步机制的实现均依赖于对改变量的原子操做。为了实现不一样的同步机制,咱们须要建立一个非共有的(non-public internal)扩展了AQS类的内部辅助类来实现相应的同步逻辑,AbstractQueuedSynchronizer并不实现任何同步接口,它提供了一些能够被具体实现类直接调用的一些原子操做方法来重写相应的同步逻辑。AQS同时提供了互斥模式(exclusive)和共享模式(shared)两种不一样的同步逻辑。
本质上有两大类:共享内存机制和消息通讯机制。
java内存模型(即Java Memory Model,简称JMM)自己是一种抽象的概念,并不真实的存在,它描述一组规范或者规则,经过这组规范定义了程序中各个变量的访问方式。
JMM中的主内存:
JMM中的工做内存:
JMM与java内存区域划分是不一样的概念层次:
JMM如何解决可见性问题:
compare and swap:
为何要使用线程池
J.U.C的三个Executor接口
线程池的状态:
线程池的大小如何选定:
线程池的参数
线程池的任务提交:线程池框架提供了两种方式提交任务,根据不一样的业务需求选择不一样的方式。
线程池任务的执行:具体的执行流程以下:
addWoker方法实现的前半部分:
一、判断线程池的状态,若是线程池的状态值大于或等SHUTDOWN,则不处理提交的任务,直接返回;
二、经过参数core判断当前须要建立的线程是否为核心线程,若是core为true,且当前线程数小于corePoolSize,则跳出循环,开始建立新的线程,具体实现以下:
线程池的工做线程经过Woker类实现,在ReentrantLock锁的保证下,把Woker实例插入到HashSet后,并启动Woker中的线程,其中Worker类设计以下:
runWorker方法是线程池的核心:
getTask实现:
Future和Callable实现:在实际业务场景中,Future和Callable基本是成对出现的,Callable负责产生结果,Future负责获取结果。
协程(Coroutine)这个词其实有不少叫法,好比有的人喜欢称为纤程(Fiber),或者绿色线程(GreenThread)。其实究其本质,对于协程最直观的解释是线程的线程。虽然读上去有点拗口,但本质上就是这样。
协程的核心在于调度那块由他来负责解决,遇到阻塞操做,马上放弃掉,而且记录当前栈上的数据,阻塞完后马上再找一个线程恢复栈并把阻塞的结果放到这个线程上去跑,这样看上去好像跟写同步代码没有任何差异,这整个流程能够称为coroutine,而跑在由coroutine负责调度的线程称为Fiber。
早期,在JVM上实现协程通常会使用kilim,不过这个工具已经好久不更新了,如今经常使用的工具是Quasar,而本文章会所有基于Quasar来介绍。