进程同步和线程同步概述

楼主本来是要继续写服务器并发的,但是后续的服务器相关点都和进程线程联系在一起,所以先把进程线程相关内容写完吧! 这次只写进程线程的概述,实际操作后续博文逐一代码实现。

进程同步or进程通信/线程同步or线程通信? 这两组概念迷惑我至今,网上和书籍对这个的描述也是爱用啥用啥的感觉,今天又重新理了一遍。

什么是同步:同步就是数据保持一致,无论是进程还是线程,都是实现了代码执行流程的分支,多个分支同时进行。多个分支互不干扰,但是又有些数据需要共享,让这些数据对所有分支保持一致即为同步。 什么是通信:通信就是数据传输,数据存在两块不同的内存区域。通过某种方式互相传递。 但是在进程线程中,比如面试官问你进程同步有那些方式,管道算是同步还是通信?干脆也懒得区分,还是按传统习惯,同步,通信一并处理吧,理解成同一个玩意。

进程: linix一个程序就是一个进程,想产生新的进程只有唯一的一个方法:fork(),这里不讨论开启或调用其他程序场景。 进程完全拷贝资源,两个进程完全独立,从fork()那段代码开始,复制执行完毕的代码内存,然后分道扬镳各自独立执行,进程的数据不是共享的,同一变量占用的内存地址不一样。 虽然完全一致,还是有父子区别的,fork()返回两次,返回值为0的是子进程,返回子进程pid的是父进程。 使用进程要注意什么:

  1. 父进程不回收子进程会产生僵尸进程,即子结束了父还在执行并且没有回收导致子进程依然占用内核资源,解决办法为捕获子进程结束信号,执行waitpid回收子进程。
  2. 进程最好在代码较干净时产生,在多线程下产生进程要重置锁状态,如本进程拷贝锁状态,产生进程后用户认为是空闲的,但实际其他进程占用锁,可能导致获取锁阻塞。
  3. fork()拷贝代码所有资源,但是不拷贝线程。在线程下执行fork(),不会拷贝其他线程,只拷贝本进程,所以才会产生2描述的死锁。
  4. 使用临界资源时需要获得信号量,保证临界资源的唯一访问。

进程同步方式:

  1. 管道,只局限与父子进程。
  2. 信号,进程间传递信号,捕获到信号后执行对应绑定的代码,和QT的信号槽类似。可以实现进程通信的“单播”、“广播”。
  3. 信号量,信号量本身无法传递数据,配合共享内存使用,类似于线程中的锁,用于保护临界资源。
  4. 共享内存,进程间最常用的数据同步方式。与信号量配合使用。
  5. 消息队列,也是非常常见的同步方式,把数据放入队列,内核逐一处理发送至目的线程。
  6. socket ? 网上很多提及到这种方式,但是《Unix网络编程》、《Linux高性能服务器编程》及自己工作中都没见过这种方式,有消息队列为何还要用socket?应用层一直到链路层,效率应该不怎么样吧,对网上这提出的socket保持怀疑态度,主机间还是可以理解的。

线程: linux线程直到1996年才出现,Linux线程分LinuxThread和NPTL两个版本,可使用getconf GNU_LIBPTHREAD_VERSION 查看。 前者实际上是进程的衍生版的轻量级进程,效率较低,占用资源多,现在已经被抛弃的差不多了。后者是真正意义上的线程,不会产生进程。 线程里数据是共享的,即同一变量占用同一个内存地址,所以用全局变量就可以轻松实现数据交流。 使用线程要注意什么:

  1. 线程创建后处于join态,结束时类似进程,需要进行回收:pthread_join()。也可以创建后将其join态置为脱离态,结束自动销毁。
  2. 线程访问临界资源需要信号量或互斥锁控制,有时还需要控制变量控制线程先后。
  3. 线程分抢占式和非抢占式,抢占式即每个线程轮流占用一段时间,这个时间是2毫秒,非抢占式按优先级轮流执行,时间不限。这个即线程调度。
  4. 使用线程是加锁先后和解锁先后要按优先级顺序避免死锁,同时也切忌两次加锁产生死锁。
  5. 线程函数无入参无返回值,当一个类成员函数作为线程函数时必须用static修饰,弱化成员函数,让成员函数没有this指针。

线程同步方式:

  1. 信号,使用方法和进程几乎一样,但是是另一套相似的API,不可以互换。
  2. 信号量,和进程类似,功能和互斥锁基本一样。
  3. 互斥锁,保护临界资源。
  4. 控制变量,常和互斥锁配合使用,控制线程执行的先后。暂时挂起线程还锁,解决线程为获得数据等待其他线程,导致长时间占用锁。

至此,总结了进程和线程使用时要注意的地方和较为齐全的各自的同步方式。面试官的最爱内容,后续博文将用代码逐一实现他们!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏张善友的专栏

关于gcc、glibc和binutils模块之间的关系

一、关于gcc、glibc和binutils模块之间的关系 1、gcc(gnu collect compiler)是一组编译工具的总称。它主要完成的工作任务是“...

25180
来自专栏cloudskyme

jbpm5.1介绍(3)

在您好的应用程序中使用一个新的流程 流程处理  (1)你需要建立一个知识库,其中包含过程定义 KnowledgeBuilder kbuilder = Knowl...

37840
来自专栏微信公众号:Java团长

Java Web从前端到后台常用框架介绍

Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解...

25130
来自专栏IMWeb前端团队

RESTful API 规范 v1.0

本文作者:IMWeb 梁伟盛 原文出处:IMWeb社区 未经同意,禁止转载 RESTful API 规范 v1.0 [toc] URI URI规范 不...

30870
来自专栏北京马哥教育

29 条运维工程师必会实用 Linux 命令

虽然Linux发行版支持各种各样的饿GUI(graphical user interfaces),但在某些情况下,Linux的命令行接口(bash)仍然是简单...

32890
来自专栏JavaEdge

大道缓存1 缓存特征2 缓存介质3 缓存分类和应用场景缓存实战

用户请求从界面(浏览器/App)到网络转发、应用服务再到存储(数据库或文件系统),然后返回到界面呈现内容。

13010
来自专栏Java帮帮-微信公众号-技术文章全总结

Web-第三十一天 WebService学习【悟空教程】

简单的网络应用使用单一语言写成,它的唯一外部程序就是它所依赖的数据库。大家想想是不是这样呢?

23540
来自专栏闵开慧

Java heap space

其实这样的错误有时候并不是程序逻辑的问题(当然有可能是由于程序写的不够高效,产生的内存消耗不合理而导致),而是由于同样的作业,在数据量和数据本身发生不同时就会占...

30990
来自专栏大魏分享(微信公众号:david-share)

实战:Bean的数据完整性验证方法| 从开发角度看应用架构11

Java应用程序将数据存储在Java对象中。这些Java对象通过网络,作为参数传递给方法,并存在于Java EE应用程序的不同层中。为了保持数据完整性,数据验证...

14530
来自专栏Kevin-ZhangCG

[ Java面试题 ] 框架篇

  1. struts是一个按MVC模式设计的Web层框架,其实它就是一个Servlet,这个Servlet名为ActionServlet,或是ActionSe...

17320

扫码关注云+社区

领取腾讯云代金券