作为顶层应用开发者,我们关注的不仅仅是数目庞大的API,也要定性的理解计算机体系中每一个层次的逻辑。
生产者消费者问题和哲学家问题中,我们可以将产品库或筷子视作临界资源,不同进程或者线程对临界资源的读写就引出了线程同步或者进程同步。
保护临界资源/进行通信可以理解为进程同步或者线程同步,其中线程同步的方法有互斥量、读写锁、自旋锁、条件变量,进程同步的方法有共享内存、域套接字等。一系列的操作不能被中断就可以称这些操作具有原子性。原子是物质所表现出特性的基本单位。
互斥量(互斥锁)
当一个线程开始读写临界资源时,首先对临界资源加锁,操作完成后,再对临界资源解锁。保证线程串行的读写临界资源。也就是说当前只能有一个线程读写临界资源,其他线程只能等待。
自旋锁
当临界资源加上自旋锁后,多线程读写此临界资源时,就开始反复检查锁变量对于自身线程来说是否可用。保证线程串行的读写临界资源。减少自旋锁不会让出CPU。避免了进程或线程上下文切换的开销。
读写锁
读写锁是一种特殊的自旋锁。读操作和写操作是互斥的,而读操作与读操作是不互斥的,适合多读少写的场景。
条件变量
条件变量允许线程睡眠,直到满足某种条件;当满足某种条件时,可以向该线程发出信号,通知唤醒。需要配合互斥量使用。
等待条件满足,等待被唤醒。
同步方法 | 描述 |
---|---|
互斥锁 | 最简单的一种线程同步方法,会阻塞线程 |
自旋锁 | 避免切换的一种线程同步方法,属于忙等待 |
读写锁 | 为读多写少的资源设计的线程同步方法,可以显著提高性能 |
条件变量 | 相对复杂的线程同步方法,有更灵活的使用场景 |
创建进程
fork系统调用用于创建新的进程,fork创建的进程的初始化状态与父进程一样,系统会为新创建的进程分配资源。
fork函数没有参数,调用一次返回两次分别返回子进程ID和0。第一次是由父进程返回的,第二次是由子进程返回的。返回子进程的ID的是父进程,返回0的是子进程。
进程同步的方法——共享内存
共享内存是不相关的进程访问的同一片物理内存,是进程间共享和传递数据最快的一种方式。共享内存没有提供同步机制,需要借助其他机制管理访问。
使用共享内存的四个步骤:
申请共享内存
连接到进程空间
使用共享内存
脱离进程空间&删除
共享内存是高性能后台开发中最常用的进程同步方式。
进程同步的方法——Unix域套接字
套接字(Socket)原是网络通信中的使用的术语,Unix系统提供的域套接字提供了网络套接字类似的功能。
服务端使用方法:创建套接字、绑定套接字、监听、处理和接收信息。
客户端使用方法:创建套接字、连接套接字、发送信息。
提供了单机简单可靠的进程通信同步服务。