进程同步和线程同步

版权声明:本文为博主原创文章,from http://blog.csdn.net/u013074465。 https://blog.csdn.net/u013074465/article/details/46271495

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

         互斥锁和条件变量是同步的基本组成部分。互斥锁和条件变量出自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节),或者给该应用提供满足所需优先关系的专用读写锁实现。

展开阅读全文

没有更多推荐了,返回首页