多线程学习笔记(一)--多线程相关概念

  • 前言

究竟什么时候要使用并行呢?是什么场景都可以达到我们预想的那样高性能吗?2014年底,Avoiding ping pong论坛上,Linus Torvalds提出了一个截然不同的观点,Give it up,The whole "parallel computing is the future "  is a bunch of crock.并行程序的设计和实现异常复杂,不仅仅体现在程序的功能分离上,多线程间的协调性,乱序性都会成为程序正确执行的障碍,但有些时候我们会很自然的使用,例如,要去处理一张照片时,一张拥有1024*768像素的图片,如果要每一个像素都遍历一下,那需要的时间是相当多的,这时候用多线程去访问,就会很容易解决问题。

  • 同步和异步

 同步方法一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为,异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者就可以继续后续的操作,整个过程不会阻碍调用者的工作,如果异步调用需要返回结果,那么当这个异步调用真的完成时则会通知调用者。


  • 并行和并发

 并发表示多个任务交替进行,并行是多个任务''同时执行"


  • 临界区
 表示一种公共资源或者共享资源,可以被多个线程使用,但在同一时刻每一次只能有一个线程使用它,一旦临界区资源被占用,其他线程想使用这个资源,就必须等待。
  • 阻塞和非阻塞
 通常用来形容多线程间的相互影响,比如一个线程占用了临界区资源,那么其他所有需要这个资源的线程就必须在临界区等待,等待时会将线程挂起,这就是阻塞,若这个临界区资源不被释放,则整个临界区的线程都不能正常的工作。非阻塞表示线程间不会互相影响,所有线程都可以向前执行。
  • 死锁,饥饿和活锁

 死锁:这种情况最严重,多个线程都占用部分资源,所以线程都在等待其他线程释放资源,谁也不释放,就导致了死锁的发生。

饥饿:某个进程由于某些原因(如优先级太低)一直获取不到所需要的资源,导致一直执行不下午

活锁:死锁是互相不释放资源,活锁是互相都释放资源,导致资源不断的在两个线程间跳动,但是谁也不能拿到所有资源执行

  • 并发级别
 由于临界区的存在,多线程之间的并发必须受到控制,根据控制并发的策略,将并发级别分为阻塞,无饥饿,无障碍,无锁,无等待
  • 无饥饿
 若锁是不公平的,优先级高的线程可以插队去访问临界区的资源,就可能导致优先级低的线程饥饿,若采用公平的锁,所有的线程按照顺序去访问,则不会出现线程饥饿的情况。
  • 无障碍
 多个线程都可以进入临界区,而不会因为临界区的问题导致一个线程被 挂起,但如果多个线程都对临界区内的数据进行修改,则会导致数据不安全,检测到这种情况后,程序会立即对自己所做的修改进行回滚。这又可能导致另一种情况发生,程序会不断的回滚自己当前的操作,一种可行的无障碍实现可以依赖"一致性标记"实现,线程 操作之前先读取并保存这个一致性标记,操作完成后再次读取对比两次是否一样,一样则表示无冲突,不一样则表示数据有冲突,则需要重试。
  • 无等待
 要求所有线程都能在有限步内完成操作。
  • 无锁
  无锁的并行是无障碍的,无锁情况下,所有线程都能尝试对临界区进行访问,但,无锁的并发保证必然有一个线程能够再有限步内完成操作离开临界区。
  • 三大特性(原子性,可见性,有序性)

 原子性:一个操作是不可中断的,即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。

 可见性:当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改

 有序性:在线程并发情况下,指令可能重排,可能导致指令运行顺序和想象中的不同。

  • 线程安全
当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类就是线程安全的(会引起锁竞争问题)

猜你喜欢

转载自blog.csdn.net/zh15732621679/article/details/80041799