并发
并发是指一个处理器同时处理多个任务,交替执行。有处理多个任务的能力,但不一定是同时处理。
并行
并行是指多个处理器或者是多核的处理器同时处理多个不同的任务。 有同时处理多个任务的能力,关键点是“同时处理”。
并发是逻辑上的同时发生(simultaneous),而并行是物理上的同时发生。并发就像一个人(CPU)喂两个小孩(程序)吃饭,表面上是两个小孩在吃饭,实际是一个人在喂。 并行就是两个人喂两个小孩子吃饭。
与多线程的关系
并行需要两个或两个以上的线程跑在不同的处理器上,并发可以跑在一个处理器上通过时间片进行切换。
同步(Sync)
所谓同步,就是发出一个功能调用时,在没有得到结果之前,该调用就不返回或继续执行后续操作。
异步(Async)
异步与同步相对,当一个异步过程调用发出后,调用者在没有得到结果之前,就可以继续执行后续操作。当这个调用完成后,一般通过状态、通知和回调来通知调用者。对于异步调用,调用的返回并不受调用者控制。
线程同步
是多个线程同时访问同一资源,等待资源访问结束,浪费时间,效率不高。
特点:A线程要请求某个资源,但是此资源正在被B线程使用中,因为同步机制存在,A线程请求不到,怎么办,A线程只能等待下去。
安全:线程安全
锁:synchronzied(obj){ }同一个锁
使用:要跨线程维护正确的可见性,只要在几个线程之间共享非 final 变量,就必须使用 synchronized(或 volatile)以确保一个线程可以看见另一个线程做的更改。
实现:1、ThreadLocal 2、synchronized( ) 3、wait()与 notify() 4、volatile
表现形式:1、同步代码块,被同步关键字封装的代码就是同步代码块;2、同步函数,被同步关键字修饰的函数就是同步函数。
线程异步
访问资源时,如果有空闲时间,则可在空闲等待同时访问其他资源,实现多线程机制。
特点:A线程要请求某个资源,但是此资源正在被B线程使用中,因为没有同步机制存在,A线程仍然请求的到。
安全:线程不安全,容易导致死锁
锁:synchronzied(new Object){ } 不是同一个锁
线程同步方式
1:同步方法
2:同步代码块。
3:使用重入锁实现线程同步
4:使用特殊域变量(volatile)实现线程同步
a.volatile关键字为域变量的访问提供了一种免锁机制,
b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新,
c.因此每次使用该域就要重新计算,而不是使用寄存器中的值
d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量
5:使用局部变量实现线程同步
如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,
副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。
6.使用阻塞队列实现线程同步
7.使用原子变量实现线程同步
同步方法
同步方法:使用synchronized修饰的方法,就叫做同步方法,保证一个线程执行该方法的时候,其他线程只能在方法外等着。
线程同步、异步区别
多个线程在执行的过程中是不是使用同一把锁,如果是,就是同步。如果不是,就是异步
同步必须执行到底后才能执行其他操作,异步可以同时进行。
阻塞和非阻塞
阻塞和非阻塞通常用来形容多线程间的相互影响。比如一个线程占用了临界区资源,那么其他所有需要这个而资源的线程就必须在这个临界区中进行等待。等待会导致线程挂起,这种情况就是阻塞。此时,如果占用资源的线程一直不愿意释放资源,那么其他所有阻塞在这个临界区上的线程都不能工作。非阻塞的意思与之相反,它强调没有一个线程可以妨碍其他线程执行。所有的线程都会尝试不断前向执行。
一、阻塞和非阻塞
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。
概括:关注的是接口调用(发出请求)后等待数据返回时的状态,描述的是一种状态。
阻塞型:被挂起无法执行其他操作的则是阻塞型的;
非阻塞型:可以被立即「抽离」去完成其他「任务」的则是非阻塞型的;
二、同步和异步
同步和异步关注的是消息通信机制。
概括:是任务完成时消息通知的方式,描述的是一种行为方式
同步:调用方盲目主动问询的方式是同步调用;
异步:被调用方自己主动通知调用方任务已完成的方式是异步调用。
1、同步机制: 发送方发送请求之后,需要等接收方发回响应后才接着发
2、异步机制: 发送方发送一个请求之后不等待接收方响应这个请求,就继续发送下个请求。
3、阻塞调用调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回,该线程在此过程中不能进行其他处理
4、非阻塞调用调用结果不能马上返回,当前线程也不会被挂起,而是立即返回执行下一个调用。(网络通信中主要指的是网络套接字Socket的阻塞和非阻塞方式,而soket 的实质也就是IO操作)
5、同步阻塞方式 发送方发送请求之后一直等待响应。接收方处理请求时进行的IO操作如果不能马上等到返回结果,就一直等到返回结果后,才响应发送方,期间不能进行其他工作
6、同步非阻塞方式发送方发送请求之后,一直等待响应,接受方处理请求时进行的IO操作如果不能马上的得到结果,就立即返回,取做其他事情。但是由于没有得到请求处理结果,不响应发送方,发送方一直等待。一直等到IO操作完成后,接收方获得结果响应发送发后,接收方才进入下一次请求过程。(实际不应用)
7、异步阻塞方式 发送方向接收方请求后,不等待响应,可以继续其他工作,接收方处理请求时进行IO操作如果不能马上得到结果,就一直等到返回结果后,才响应发送方,期间不能进行其他操作。 (实际不应用)
8、异步非阻塞方式发送方向接收方请求后,不等待响应,可以继续其他工作,接收方处理请求时进行IO操作如果不能马上得到结果,也不等待,而是马上返回取做其他事情。当IO操作完成以后,将完成状态和结果通知接收方,接收方在响应发送方。(效率最高)
阻塞和非阻塞的本质
本质是描述该线程在CPU里的执行方式。
阻塞:被CPU暂时挂起来了
非阻塞:一直占用CPU运行
很多时候我们会误以为同步天然就是阻塞的,异步天然就是非阻塞的。其实不是这样的,它们之间可以互相组合成四组概念:同步阻塞、同步非阻塞、异步阻塞、异步非阻塞。
同步阻塞
例如使用wait函数傻等的:
1 obj.wait(timeout)
在超时期间,该线程会被CPU挂起,这就是同步阻塞。
同步非阻塞
通过while循环判断共享变量,condition为设置的共享变量
while(flag){
if(condition)
flag = false;
}
那么该线程会一直占着CPU,这就是非阻塞同步。
异步的阻塞和非阻塞
阻塞性异步和非阻塞性异步并不像之前的两个概念那么好理解。解答这个问题之前,先提一个思考问题:异步线程在执行的时候,主线程在做什么?
从直观上来看, KeepTalking()是否存在与是否阻塞没有关系。可是 KeepTalking()正是主线程里并行和异步线程执行的任务。
如果不存在,那么就意味着主线程在异步等待时任务为空。而它是否存在是区别是否阻塞的唯一线索。
异步阻塞
如果狗在捡球的同时没有任何动作,只是干等着狗回来。就是阻塞的异步。这里的阻塞是通过什么都不干的方式来实现不占用CPU,这倒也符合我们在之前谈到的阻塞的定义:阻塞线程不占用CPU。其实强行区分异步和阻塞没有什么意义。
异步非阻塞
如果狗在捡球的同时,你在和朋友聊天或者干点别的什么,这就是非阻塞的异步。现实中,非阻塞的异步占据绝大多数。
网友评论