Skip to content

进程和线程

进程是资源分配的基本单位,线程是CPU调度的基本单位。 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。

临界资源

原语 (Primitive)

指在操作系统或并发编程中,一种不可分割的操作或指令。原语在执行过程中不能被中断,必须作为一个整体完成,以确保操作的完整性和正确性。原语通常用于实现同步机制,如互斥锁、信号量等。

管程 (Monitor)

特点

  • 互斥访问: 确保任何时刻只有一个线程访问管程中的共享数据。
  • 条件变量: 用于线程同步,允许线程在某些情况下等待,直到某些条件满足。
  • 线程安全: 程序员不必再手动管理锁和条件变量

使用Go语言的包实现管程, example:

go
package main

import (
	"fmt"
	"sync"
	"time"
)

var (
    condition = false
    mutex = sync.Mutex
    cond = sync.NewCond(&mutex) // 创建一个条件变量
)

func waitCondition() {
    mutex.Lock() // 获取锁
    for !condition {
        cond.Wait() // 等待条件变量满足
    }
    fmt.Println("Condition met, proceeding...")
	mutex.Unlock()
}

func setCondition() {
    mutex.Lock() // 获取锁
    condition = true
    cond.Broadcast() // 通知所有等待的线程
    mutex.Unlock() // 释放锁
}

func main() {
    go waitCondition()
    time.Sleep(1 * time.Second) // 模拟一些工作
	setCondition()
	time.Sleep(1 * time.Second) // 等待线程完成
}

/**
sync.NewCond(&mutex) 

*/

死锁 (Deadlock)

死锁是指两个或多个进程在执行过程中,因争夺资源而造成的一种僵局(Deadly Embrace),若无外力作用,这些进程将无法继续执行

处理办法

  • 预防死锁: 通过破坏四个必要条件之一, 就可以避免死锁的发生。

    • 互斥: 一个资源只能被一个进程使用, 其他进程必须等待。
    • 请求和保持条件: 一个进程占有资源后, 在请求其他资源, 保持已分配的资源。
    • 不可抢占: 一个进程不能抢占其他进程的资源, 只能等它完成后主动释放资源。
    • 循环等待条件:存在一个进程资源的循环链,每个进程都在等待下一个进程所持有的资源。
  • 避免死锁: 避免死锁的发生, 例如使用互斥锁、信号量等机制来确保资源的互斥访问。

  • 避免死锁的发生, 例如使用互斥锁、信号量等机制来确保资源的互斥访问。

  • 检测与解除死锁:允许系统进入死锁状态,但定期检测死锁的发生,并采取措施解除死锁。

死锁与安全状态的关系

  • 安全状态:系统能够按照某种顺序分配资源,确保所有进程都能完成,而不发生死锁。
  • 不安全状态:系统无法保证所有进程都能完成,可能陷入死锁状态。
  • 死锁状态(Deadlock State):系统已经陷入无法继续执行的僵局,所有进程都在等待资源,无法继续执行。

信号量 (Semaphore)

  • wait(也称为P操作)

尝试获取资源, 如果信号量的值大于0,则将其减1并继续执行;如果信号量的值小于或等于0,则当前进程会被阻塞,并加入到阻塞队列中。

go
func wait(S) {
    S.value--
    if S.value < 0 {
        // 将当前进程加入阻塞队列
        block(S.queue)
    }
}
  • signal(也称为V操作)。

释放资源。如果阻塞队列中有进程等待资源,则唤醒其中一个进程;否则,将信号量的值加1。

为负就是阻塞;

go
func signal(S) {
    S.value++
    if S.value <= 0 {
        // 从阻塞队列中唤醒一个进程
        wakeup(S.queue)
    }
}

使用场景

  • 互斥: 多个线程需要访问同一个资源, 但只有一个线程可以访问该资源, 其他线程需要等待。
go
var mutex = &sync.Mutex{}

func criticalSection() {
    mutex.Lock()
    // 临界区代码
    mutex.Unlock()
}

PCB(Process Control Block)

  • 资源管理

使用计数信号量(初始值为可用资源的数量)来管理有限数量的资源。

调度算法:

  • 先到先服务(FCFS, First-Come, First-Served):按照进程到达的时间顺序进行调度。 平均等待时间较长,可能导致“饥饿”现象。
  • 短作业优先(SJF, Shortest Job First):选择等待时间最短的进程进行调度。 平均等待时间较短,但可能导致饥饿现象。
  • 优先级调度:根据进程的优先级进行调度。 能导致低优先级进程“饥饿”。
  • 时间片轮转(RR, Round Robin):每个进程被分配一个固定长度的时间片,时间片用完后,进程被放回就绪队列,等待下一次调度。 优点:公平性好,适合分时系统。
  • 多级反馈队列调度(MFQ, Multilevel Feedback Queue):多个队列,每个队列有不同的优先级和时间片长度。进程在不同队列之间移动,根据其行为调整优先级。

系统

  • 分时系统(Time-Sharing System): 多个用户共享一个计算机系统, 每个用户轮流使用计算机系统, 每个用户在计算机系统中占用的时间片段称为一个时间片。

用户较多的时候, 系统的响应速度会变慢。

  • 实时系统(Real-Time System): 要求系统在规定的时间内完成规定的任务, 否则系统将自动采取措施, 以保证系统的安全性和可靠性。

实时系统通常不强调广泛的交互性能,而是注重快速响应和高可靠性。

  • 批处理系统(Batch Processing System): 批处理系统是一种将多个作业(任务)成批提交给计算机处理的系统。系统按照提交的顺序依次处理每个作业,用户无法实时与系统进行交互。

无法实时交互的批处理系统, 通常使用批处理系统来处理实时任务。

  • 多道程序设计(Multiprogramming): 多道程序设计是指在计算机系统中同时运行多个程序, 每个程序称为一个进程。
本站访客数 人次 本站总访问量