操作系统知识点梳理(二)

操作系统知识点梳理(二)

进程/线程间通信方式

继续(一)之后,梳理进程/线程间通信方式主要知识点,参考资料:

  • https://mp.weixin.qq.com/s/mblyh6XrLj1bCwL0Evs-Vg
  • https://blog.csdn.net/weixin_40418080/article/details/125491961

进程间通信

  1. 管道
  • 管道本质上就是内核中的一个缓存,当进程创建一个管道后,Linux会返回两个文件描述符,一个是写入端的描述符,一个是输出端的描述符,可以通过这两个描述符往管道写入或者读取数据,如果想要实现两个进程通过管道来通信,则需要让创建的管道的进程fork子进程,这样子进程就拥有了父进程的文件描述符,这样子进程之间也就有了对同一管道的操作
  • 缺点
    • 半双工通信,一条管道只能一个进程写,一个进程读
    • 一个进程写完后,另一个进程才能读,反之同理
  1. 消息队列
  • 消息队列是保存在内核中的消息链表,在发送数据时,会分成一个一个独立的数据单元,也就是消息体(数据块),消息体是用户自定义的数据类型,消息的发送方和接收方要约定好消息体的数据类型,所以每个消息体都是固定大小的存储块,不像管道是无格式的字节流数据。
  • 优点:消息队列适合进程间频繁地交换数据,两个进程之间的通信就像平时发邮件一样,你来一封,我回一封,可以频繁沟通
  • 缺点:
    • 消息队列不适合大数据的传输
    • 通信不及时,消息队列通信过程中,存在用户态和内核态之间的数据拷贝开销
  1. 共享内存
  • 共享内存的机制,就是拿出一块虚拟地址空间来,映射到相同的物理内存中。这样这个进程写入的东西,另一个进程马上就能看到,都不需要拷贝来拷贝去,大大提高了进程间通信的速度
  • 缺点:多个进程同时修改一个共享内存,很有可能冲突
  1. 信号量
  • 为了防止多进程竞争共享资源,而造成数据错乱,所以需要保护机制,使得共享的资源,在任意时刻只能被一个进程访问,信号量实现了这一保护机制
  • 信号量其实是一个整型的计数器,主要用于实现进程间的互斥与同步,而不是用于缓存进程间通信的数据
  • 控制信号量的方式有两种原子操作
    • 一个是P操作:这个操作会把信号量减去-1,相减后如果信号量<0,则表明资源已被占用,进程需阻塞等待;相减后如果信号量>=0,则表明还有资源可使用,进程可正常继续执行
    • 一个是V操作:这个操作会把信号量加上1,相加后如果信号量<=0,则表明当前有阻塞中的进程,于是会将改进程唤醒运行;相加后如果信号量>0,则表明当前没有阻塞的进程
  • 信号量初始化
    • 初始化为1代表着互斥信号量
    • 初始化为0代表着同步信号量
  1. 信号
  • 对于异常情况下的工作模式,就需要用【信号】的方式来通知进程
  • 信号是进程间通信机制中唯一的异步通信机制,因为可以在任何时候发送信号给某一进程,一旦有信号产生,有以下几种用户进程对信号的处理方式
    • 执行默认操作
    • 捕捉信号
    • 忽略信号
  1. Socket
  • 跨网络与不同主机上的进程之间通信
    • 基于TCP协议通信方式
    • 基于UDP协议通信方式
    • 本地进程间通信方式

线程间通信

  1. 等待–通知
  • 等待–通知机制相关方法:
    • notify():通知一个对象上等待的线程,使其从wait()方法返回,而返回的前提是该线程取得了对象的锁
    • notifyAll():通知所有等待在该对象上的线程
    • wait():调用该方法的线程进程WAITING状态,只有等待另外线程的通知或被中断才会返回,调用wait()方法后,会释放对象的锁
    • wait(long timeout):超过等待一段时间,没有通知就超时返回,参数时间是毫秒
  • 注意事项
    • 等待–通知机制使用的是同一个对象的锁,如果两个进程使用的是不同的对象锁,那它们之间是不能用等待–通知机制通信的
    • 使用wait()、notify()和notifyAll()时需要先对调用对象加锁
    • 调用wait()方法后,线程状态由RUNNING变为WAITING,并将当前线程放置到对象的等待队列
    • notify()或notifyAll()方法调用后,等待线程依旧不会从wait()返回,需要调用notify()或notifyAll()的线程释放锁之后,等待线程才有机会从wait()返回
    • notify()方法将等待队列中的一个等待线程从等待队列中移动到同步队列中,而notifyAll()方法则是将等待队列中所有的线程全部移动到同步队列,被移动的线程状态由WAITING变为BLOCKED
    • 从wait()方法返回的前提是获得了调用对象的锁
  • wait()方法的核心原理
    • 当线程调用了locko(某个同步锁对象)的wait()方法后,JVM会将当前线程加入locko监视器的WaitSet(等待集),等待被其他线程唤醒。
    • 当前线程会释放locko对象监视器的Owner权限,让其他线程可以抢夺locko对象的监视器
    • 让当前线程等待,其状态变成WAITING
  • notify()方法的核心原理
    • 当线程调用了locko(某个同步锁对象)的notify()方法后,JVM会唤醒locko监视器WaitSet中的第一条等待线程
    • 当线程调用了locko的notifyAll()方法后,JVM会唤醒locko监视器WaitSet中的所有等待线程
    • 等待线程被唤醒后,会从监视器的WaitSet移动到EntryList,线程具备了排队抢夺监视器Owner权利的资格,其状态从WAITING变成BOLOKED
  1. 共享内存
  • 同步–synchronized
    • 关键字synchronized可以修饰方法或同步块,它主要确保多个线程在同一时刻,只能有一个线程处于方法或同步块中,它保证了线程对变量访问的可见性和排他性
  • 信号量–volatile
    • 关键字volatile可以用来修饰字段(成员变量),就是告诉程序对该变量的访问需要从共享内存中获取,而对它的改变必须同步刷新回共享内存,它能保证所有线程对变量访问的可见性
    • volatile能够保证内存的可见性,如果在一个线程里改变了这个变量的值(该变量是由volatile关键字修饰的),那么其它线程对这种改变是立马可见的。
  • 循环队列:生产者消费者模型
  1. 管道流
  2. ReentrantLock/Condition 消息队列方式
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值