进程同步和线程同步

2024-08-28 04:08
文章标签 线程 同步 进程同步

本文主要是介绍进程同步和线程同步,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

         怎样同步多个线程或多个进程的活动。为允许在线程或进程间共享数据,同步是必需的。

         互斥锁和条件变量是同步的基本组成部分。互斥锁和条件变量出自POSIX.1线程标准,它们总是可用来同步一个进程内的各个线程的。如果一个互斥锁或条件变量存放在多个进程间共享的某个内存中,那么POSIX还允许它用于这些进程间的同步互斥锁、条件变量、读写锁、信号量均可用于进程、线程的同步

多线程同步方法

1)互斥量(互斥锁)

参考资料:互斥量:APUE第二版299页;  条件变量:第309页;  同步属性:318页。

         互斥锁是最基本的同步形式,用于保护临界区,确保同一时间只有一个线程或进程访问数据或执行其中的代码。互斥量(mutex)本质上是一把锁,访问共享资源前要对互斥量加锁,访问完后要释放锁。

        互斥量用于上锁,而条件变量用于等待

        允许多个进程将同一个内存区域映射到它们各自独立的地址空间,就像多线程一样共享数据,那么多个进程访问共享数据通常也需要同步。如果进程共享互斥量属性设置为PTHREAD_PROCESS_SHARED从多个进程共享的内存区域中分配的互斥量就可以用于这些进程的同步了。进程共享互斥量属性设为PTHREAD_PROCESS_PRIVATE时,允许pthread线程库提供更加有效的互斥量实现,这在多线程应用程序中是默认的情况。

       用于给存放在共享内存区中供多个进程使用的条件变量设置PTHREAD_PROCESS_SHARED属性的一组语句跟用于互斥锁的语句几乎相同,只需要将mutex替换为cond。

2)条件变量

         条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定条件发送。条件变量本身是由互斥量保护的。线程在改变条件状态前必须首先锁住互斥量,必须锁住互斥量以后才能计算条件。如果在规定的时间内条件满足就通知线程,否则生成一个代表出错码的返回变量。

        可以用于进程的同步,设置PTHREAD_PROCESS_SHARED属性。


3)读写锁(共享-独占锁)

        和互斥量类似,不过读写锁允许更高的并行性。互斥量要么是锁住状态要么是不加锁状态,而且一次仅允许一个线程对互斥量加锁。

        读写锁有三种状态:a. 读模式下加锁状态(所有试图以读模式对其进行加锁的线程都可以获得访问权,但如果试图以写模式加锁,必须阻塞直到所有线程释放读锁);b. 写模式下加锁状态(在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞);c. 不加锁状态。

        可用于进程、线程之间的同步

4)信号量

信号量可用于线程或进程间同步

        信号量是一个计数器,用于多进程对共享数据对象的访问。若此信号量的值为正,则进程可以使用该资源;进程将信号量减1,表示它使用了一个资源单元。若此信号量的值为0,则进程进入休眠状态,直至信号量位于0。若一个进程不再使用由一个信号量控制的共享资源时,该信号量值增1。如果有进程正在休眠等待此信号量,则唤醒它们。

POSIX信号量:

参考:UNP卷2第10章

        POSIX信号量可以是有名的,也可以是基于内存的。有名信号量总是能够在不同进程间共享,基于内存的信号量则必须在创建时指定成是否在进程间共享。这两类信号量的持续性也有差别:有名信号量至少是随内核持续的,基于内存的信号量则是具有随进程持续的。

System V信号量

如同进程一样,线程也可以通过信号量来实现通信,虽然是轻量级的。信号量函数的名字都以"sem_"打头。线程使用的基本信号量函数有四个。

  1. 信号量初始化。
    int sem_init (sem_t *sem , int pshared, unsigned int value);
    这是对由sem指定的信号量进行初始化,设置好它的共享选项(linux 只支持为0,即表示它是当前进程的局部信号量),然后给它一个初始值VALUE。
  2. 等待信号量。给信号量减1,然后等待直到信号量的值大于0。
    int sem_wait(sem_t *sem);
  3. 释放信号量。信号量值加1。并通知其他等待线程。
    int sem_post(sem_t *sem);
  4. 销毁信号量。我们用完信号量后都它进行清理。归还占有的一切资源。
    int sem_destroy(sem_t *sem);

进程间同步方法

上述提到的互斥量、条件变量、读写锁、信号量都可用于进程间同步

互斥量

条件变量

读写锁

信号量

记录锁

        Linux内核没有文件内的记录这一概念。任何关于记录的接收都是由读写文件的应用来进行的。然而linux内核提供的上锁特性却用记录上锁(record locking)这一术语描述。不过应用会指定文件中待上锁或解锁部分的字节范围,因为记录锁锁定的只是文件中的一个区域。

       记录锁是读写锁的一种拓展,可用于亲缘或非亲缘关系的进程间共享某个文件的读写。被锁住的文件通过其描述符访问,执行上锁操作的函数是fcntl。这类锁通常维护在内核中,其属主是由属主的进程ID来标识的。这意味着这些锁用于不同进程间的上锁不适用于同一进程不同线程间上锁

      使用fcntl记录上锁时,等待着的读出者优先还是等待着的写入者优先没有保证;如果这对于某个应用很重要,就需要开发测试程序(UNP卷2,9.6节),或者给该应用提供满足所需优先关系的专用读写锁实现。

这篇关于进程同步和线程同步的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1113679

相关文章

Spring Boot3虚拟线程的使用步骤详解

《SpringBoot3虚拟线程的使用步骤详解》虚拟线程是Java19中引入的一个新特性,旨在通过简化线程管理来提升应用程序的并发性能,:本文主要介绍SpringBoot3虚拟线程的使用步骤,... 目录问题根源分析解决方案验证验证实验实验1:未启用keep-alive实验2:启用keep-alive扩展建

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Java终止正在运行的线程的三种方法

《Java终止正在运行的线程的三种方法》停止一个线程意味着在任务处理完任务之前停掉正在做的操作,也就是放弃当前的操作,停止一个线程可以用Thread.stop()方法,但最好不要用它,本文给大家介绍了... 目录前言1. 停止不了的线程2. 判断线程是否停止状态3. 能停止的线程–异常法4. 在沉睡中停止5

Java捕获ThreadPoolExecutor内部线程异常的四种方法

《Java捕获ThreadPoolExecutor内部线程异常的四种方法》这篇文章主要为大家详细介绍了Java捕获ThreadPoolExecutor内部线程异常的四种方法,文中的示例代码讲解详细,感... 目录方案 1方案 2方案 3方案 4结论方案 1使用 execute + try-catch 记录

Linux搭建Mysql主从同步的教程

《Linux搭建Mysql主从同步的教程》:本文主要介绍Linux搭建Mysql主从同步的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux搭建mysql主从同步1.启动mysql服务2.修改Mysql主库配置文件/etc/my.cnf3.重启主库my

Spring Boot 中正确地在异步线程中使用 HttpServletRequest的方法

《SpringBoot中正确地在异步线程中使用HttpServletRequest的方法》文章讨论了在SpringBoot中如何在异步线程中正确使用HttpServletRequest的问题,... 目录前言一、问题的来源:为什么异步线程中无法访问 HttpServletRequest?1. 请求上下文与线

在 Spring Boot 中使用异步线程时的 HttpServletRequest 复用问题记录

《在SpringBoot中使用异步线程时的HttpServletRequest复用问题记录》文章讨论了在SpringBoot中使用异步线程时,由于HttpServletRequest复用导致... 目录一、问题描述:异步线程操作导致请求复用时 Cookie 解析失败1. 场景背景2. 问题根源二、问题详细分

Java中将异步调用转为同步的五种实现方法

《Java中将异步调用转为同步的五种实现方法》本文介绍了将异步调用转为同步阻塞模式的五种方法:wait/notify、ReentrantLock+Condition、Future、CountDownL... 目录异步与同步的核心区别方法一:使用wait/notify + synchronized代码示例关键

Java多线程父线程向子线程传值问题及解决

《Java多线程父线程向子线程传值问题及解决》文章总结了5种解决父子之间数据传递困扰的解决方案,包括ThreadLocal+TaskDecorator、UserUtils、CustomTaskDeco... 目录1 背景2 ThreadLocal+TaskDecorator3 RequestContextH

java父子线程之间实现共享传递数据

《java父子线程之间实现共享传递数据》本文介绍了Java中父子线程间共享传递数据的几种方法,包括ThreadLocal变量、并发集合和内存队列或消息队列,并提醒注意并发安全问题... 目录通过 ThreadLocal 变量共享数据通过并发集合共享数据通过内存队列或消息队列共享数据注意并发安全问题总结在 J