进程同步和线程同步

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

相关文章

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后

详谈redis跟数据库的数据同步问题

《详谈redis跟数据库的数据同步问题》文章讨论了在Redis和数据库数据一致性问题上的解决方案,主要比较了先更新Redis缓存再更新数据库和先更新数据库再更新Redis缓存两种方案,文章指出,删除R... 目录一、Redis 数据库数据一致性的解决方案1.1、更新Redis缓存、删除Redis缓存的区别二

C语言线程池的常见实现方式详解

《C语言线程池的常见实现方式详解》本文介绍了如何使用C语言实现一个基本的线程池,线程池的实现包括工作线程、任务队列、任务调度、线程池的初始化、任务添加、销毁等步骤,感兴趣的朋友跟随小编一起看看吧... 目录1. 线程池的基本结构2. 线程池的实现步骤3. 线程池的核心数据结构4. 线程池的详细实现4.1 初

Java子线程无法获取Attributes的解决方法(最新推荐)

《Java子线程无法获取Attributes的解决方法(最新推荐)》在Java多线程编程中,子线程无法直接获取主线程设置的Attributes是一个常见问题,本文探讨了这一问题的原因,并提供了两种解决... 目录一、问题原因二、解决方案1. 直接传递数据2. 使用ThreadLocal(适用于线程独立数据)

Nacos集群数据同步方式

《Nacos集群数据同步方式》文章主要介绍了Nacos集群中服务注册信息的同步机制,涉及到负责节点和非负责节点之间的数据同步过程,以及DistroProtocol协议在同步中的应用... 目录引言负责节点(发起同步)DistroProtocolDistroSyncChangeTask获取同步数据getDis

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

线程的四种操作

所属专栏:Java学习        1. 线程的开启 start和run的区别: run:描述了线程要执行的任务,也可以称为线程的入口 start:调用系统函数,真正的在系统内核中创建线程(创建PCB,加入到链表中),此处的start会根据不同的系统,分别调用不同的api,创建好之后的线程,再单独去执行run(所以说,start的本质是调用系统api,系统的api

java线程深度解析(六)——线程池技术

http://blog.csdn.net/Daybreak1209/article/details/51382604 一种最为简单的线程创建和回收的方法: [html]  view plain copy new Thread(new Runnable(){                @Override               public voi

java线程深度解析(五)——并发模型(生产者-消费者)

http://blog.csdn.net/Daybreak1209/article/details/51378055 三、生产者-消费者模式     在经典的多线程模式中,生产者-消费者为多线程间协作提供了良好的解决方案。基本原理是两类线程,即若干个生产者和若干个消费者,生产者负责提交用户请求任务(到内存缓冲区),消费者线程负责处理任务(从内存缓冲区中取任务进行处理),两类线程之