JAVA并发概要

什么是JAVA并发

java并发提高程序的执行速度,然而并不是多线程就一定比单线程高效,而且并发容易出错;若要实现正确并且高效的并发,那么要注意三个问题:上下文切换、死锁、资源限制。

上下文切换

上下文切换:当一条线程的时间片使用完成后,操作系统暂停线程该线程,保存他的状态信息,然后操作系统从线程堆中随机选取一个线程来执行,这个过程,称为上下文切换。

但是:上下文切换都是有额外的开销的;

线程的运行机制

  • 一个Cpu在每个时刻只能执行一条线程
  • 操作系统给每个线程分配不同长度的时间片
  • 操作系统从线程堆中随机选取一条来执行

每条线程用完他的时间片后,尽管任务还没有完成,操作系统也会剥夺他的执行权,让其他的线程执行。

上下文切换的过程

  • 暂停正在运行的线程。
  • 保存其相关信息
  • 从队列中随机选取线程
  • 读取线程的上下文信息,继续执行

上下文切换是有额外的开销的

每次上下文切换都需要保存当前线程的执行状态,并加载新的线程的先前的状态。如果上下文切换频繁,CPU在上下文切换的时间占比就会上升,然而真正处理的任务时间就会下降。故:为了提高并发程序的执行效率,需要减少线程的数量。

上下文切换的方式

  1. 减少线程的数量。
  2. 控制同一锁上的线程数量。如果多个线程公用同一把锁,那么当其中的一个线程获得锁后,其他的线程就会被阻塞掉;当该线程释放锁后,操作系统就会用被阻塞的进程中选取一个来执行,从而造成上下文的切换。控制同一把锁下面的线程数量,可以提高并发程序的执行效率。
  3. 采用无锁开发编程。从②可得,如果不用锁的话,那么就不会产生阻塞就不会出现上下文切换。实现无锁并发编程有两种策略:①需要并发执行的任务是无状态的:HASH分段;无状态指的是在并发执行的任务之间没有共享变量,他们都是独立执行的,对其按照其ID进行HASH分段,每一段都会有一个线程执行。②需要并发执行的任务是由状态的:CAS算法;如果任务需要修改共享变量,那么必须控制线程的执行顺序,否则会出现安全问题,也可以给任务加锁,保证其原子性和可见性,但是线程执行会引发阻塞,从而出现上下文切换,使用CAS算法,在线程的内部完成共享变量的更新,就不会引发阻塞,那么就不会出现上下文切换。

死锁

当多个线程相互等待已经被对方占用资源时,就会发现死锁。

怎么避免死锁

  • 不要在同一个线程中嵌套使用多个锁。
  • 不要在同一条线程中嵌套占用多个计算机资源。
  • 如果坚持在同一个线程中嵌套使用多个锁或者占用多个计算机资源,那么需要给锁加一个超时时间,来避免相互等待的情况。

计算机的资源会限制并发

并不是线程越多速度越快

在并发编程中,有时候线程多了反而效率会低下;①线程增多导致上下文切换增加,Cpu在上下文执行的时间增多,那么相应的处理时间就减少了。②计算机资源会限制程序的并发程序。

重排序

重排序指编译器和处理器不改变运算结果的情况下,重新排列指令的执行顺序,达到最大的执行效率。

重排序分类:编译器排序和处理器排序

注意:编译器排序和处理器排序,并不会随意的改变指令的执行顺序,因为有些指令具有依赖关系的,若改变其顺序就会出现错误的结果。编译器和处理器只会对没有数据依赖关系的指令排序。

数据依赖:若相邻的两个指令访问同一个变量,并且其中有一条指令执行写操作,那么这样的两条指令存在数据依赖。对有数据依赖的指令,编译器和处理器都不会对其重排序。

数据依赖有3中情况:读后写,写后写,写后读;

posted @ 2018-09-17 10:15  轻抚丶两袖风尘  阅读(121)  评论(0编辑  收藏  举报