进程间对共享内存同步的三种方式

    如果我们有多个进程访问一块共享内存,有时候我们为了保证数据的一致我们不得不对共享内存中的数据采取同步措施。对于共享内存的同步基本上有以下三种方式。

   一 记录锁(文件锁)

      我们首先来看记录锁,记录锁的功能是当一个进程正在读或者修改文件的某一个部分时,它可以阻止其他进程修改同一文件区。它其实是“字节范围锁”,因为它锁定的是文件中的一个区域,当然,也可能是整个文件。

     进程间对共享内存同步的三种方式_第1张图片


//POSIX标准只定义fock结构中必须有以下的数据成员,具体实现可以增加
struct flock {
      short l_type;    /* 锁的类型: F_RDLCK, F_WRLCK, F_UNLCK */
      short l_whence;  /* 加锁的起始位置:SEEK_SET, SEEK_CUR, SEEK_END */
      off_t l_start;   /* 加锁的起始偏移,相对于l_whence */
      off_t l_len;     /* 上锁的字节数*/
      pid_t l_pid;     /* 已经占用锁的PID(只对F_GETLK 命令有效) */
      /*...*/
};
 进程间对共享内存同步的三种方式_第2张图片

  具体使用:高级I/O之记录锁   

二 信号量

     信号量我们都很熟悉,为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问 代码的临界区域。临界区域是指执行数据更新的代码需要独占式地执行。而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它, 也就是说信号量是用来调协进程对共享资源的访问的。它可用于线程也可用于进程,但是通常我们不用信号量来做线程间的同步,而是用互斥量,基本上对于共享内存的同步都用信号量来做。

 具体使用:linux进程间通信-信号量(semaphore)   

三 互斥量

    互斥量即我们常用的mutex,通常我们拿它来做线程间的同步,很少用来对进程间做同步,其实它也是可以做到的。

    不过我们需要把互斥量放在多进程访问的共享内存中,并且设置调用pthread_rwlockattr_setpshared linuxAPI设置PTHREAD_PROCESS_SHARED属性这样互斥量才能对多进程可见。

四 那么对于这三种到底用哪种方式好呢,

首先我们看一看他们的性能差距。下图显示了在Linux上,使用这3种不同技术进行锁操作所需的时间。在每一种情况下,资源都被分配、释放1000000次。这同时由3个不同的进程执行。

     进程间对共享内存同步的三种方式_第3张图片

   我们可以看到互斥量的性能是最好的,但是很难在多个进程间共享的内存中使用互斥量来恢复一个终止的进程(不是很理解),其次,进程共享的互斥量属性并没有得到所有平台的支持。如果我们能单一资源加锁,并且不需要信号量的其他功能,则记录锁比信号量要好。因为他使用起来更快,当进程终止时系统会管理遗留下来的锁,但是总感觉用文件锁来同步对共享内存有点怪怪的,因为信号量才是真正用来进程间同步的。最后说到信号量虽然它没有记录锁快,但是如果你对性能没有非常苛刻的要求,不论从编程的难易度还是安全性来(记录锁要依赖一个外部的文件而信号量则不需要要i)考虑信号量都是一个最好的选择。

 

你可能感兴趣的:(linux)