并发基础

概念

进程(Process)&线程(Thread)

  • 进程是系统资源分配的最小单元;线程是CPU调度的最小单元
  • 一个进程至少包含一个线程,可以包含多个线程。这些线程共享这个进程的资源
  • 每个线程都拥有独立的运行栈和程序计数器,线程切换开销小
  • 多进程指的是操作系统同时运行多个程序,如当前操作系统同时运行着QQ、微信等
  • 多线程指的是同一进程中同时运行多个线程,如迅雷运行时,可以开启多个线程,同时进行多个文件的下载

并发(Concurrency)&并行(Parallel)

并发&并行都是采用多线程技术来提高CPU的使用率

  • 并发(Concurrency)
    强调一个处理器同时处理多个任务,并不是正在同时运行
  • 并行(Parallelism)
    强调多个处理器或多核的处理器同时处理多个不同的任务,同时运行多段代码

同步

在并发中,可以将同步定义为一种协调两个或多个任务以获得预期结果的机制

  • 控制同步
    当一个任务开始依赖于另一个任务的结束时,第二个任务不能在第一个任务完成之前开始
  • 数据访问同步
    当两个或多个任务访问共享变量时,在任意时间里,只有一个任务可以访问该变量

临界区(Critical Section)是代码的一个区间,它可以访问共享资源。如果两个线程同时执行就有可能出现问题,互斥量(Mutex)是用来保护临界区。
信号量(Semaphore)是一种更高级的同步机制,Mutex 可以说是 Semaphore 在仅取值0/1时的特例。Semaphore可以有更多的取值空间,用来实现更加复杂的同步,而不单单是线程间互斥。

如果共享的数据受到同步机制的保护,那么代码(方法、对象)就是线程安全的

不可变对象

不可变对象是一种非常特殊的对象。在其初始化后,不能修改其可视状态(其属性值)。如果想修改一个不可变对象,那就必须创建一个新的对象

不可变对象主要优点在于它是线程安全的。Java 中的 String 就是一个不可变对象。

共享内存和消息传递

任务可以通过两种不同的方式来互相通信。

  • 共享内存
    通常用于在同一台计算机上运行多任务的情况。任务在读取和写入值的时候使用相同的内存区域。为了避免出现问题,对该共享内存的访问必须在一个由同步机制保护的临界段内完成
  • 消息传递
    通常用于在不同计算机上运行多任务的情形。当一个任务需要与另一个任务通信时,它会发送一个遵循预定义协议的消息。如果发送方保持阻塞并等待响应,那么该通信就是同步的;如果发送方在发送消息后继续执行自己的流程,那么该通信就是异步的。

并发的问题

数据竞争

如果两个或多个任务在临界段之外对一个共享变量进行写入操作,也就是说没有任何同步机制,那么应用程序可能存在数据竞争(也叫竞争条件

在这些情况下,应用程序的最终结果可能取决于任务的执行顺序

死锁

当两个(多个)任务正在等待必须由另一个线程释放的某个共享资源,而该线程又正在等待必须由前述任务之一释放的另一个共享资源时,并发应用程序就出现了死锁

活锁

如果系统中有两个任务,它们总是因对方的行为而改变自己的状态,那么就出现了活锁。最终结果是它们陷入了状态变更的循环而无法继续向下执行

你可能感兴趣的:(并发基础)