Linux下各种编程锁的比较[待续]

Posted 祁峰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux下各种编程锁的比较[待续]相关的知识,希望对你有一定的参考价值。


1 概述

  含有多个线程/进程的系统在运行过程中,往往会出现多个线程/进程在同一时间去读取或修改同一内存地址的数据,为了保证数据的完整性,最常用的方式是使用锁机制。编程锁有很多种,常见的有文件锁、互斥锁、读写锁、信号量、原子锁等等,虽然它们都起着保证数据完整性的作用,但是它们的作用范围、适用场景、时间开销各不相同。本篇将通过实验对各锁的适用场景、时间开销等方面做一个简单的比较和阐述,给今后工作过程中为使用哪种锁更合适而纠结时,提供一个参考依据。


2 文件锁

  在Linux系统中,文件锁的接口有3种方式:flock()、fcntl()、lockf()。以下将对这两种接口进行分别的说明。

2.1 flock()函数

表1 flock()函数说明



  其使用的参考代码如下:

图1 flock()参考代码

2.2 fcntl()函数

表2 fcntl()函数说明



  使用fcntl()实现的锁操作接口如下:


图2 fcntl()非阻塞锁操作


图3 fcntl()阻塞锁操作

  以上2个函数虽然支持读锁、写锁、解锁等操作,但是参数过多,不太好使用。为了简化接口的使用,可以使用如下宏替代:(因考虑到有线程的读写锁,而fcntl()只支持进程级的锁,因此其命名以proc_开头)

图4 锁的宏定义

2.3 lockf()函数

表3 lockf()函数说明


  使用lockf()实现的锁操作接口如下:

图5 lockf()示例代码


  以上3个函数lockf()、fcntl()、flock()实现的互斥锁、读写锁的作用域是进程级的,这种锁不能用来保证多线程中数据的安全性和一致性。

  假设:有进程3个进程A、B和C同时抢一把进程级的互斥锁L(进程A有多个线程A1、A2、...)。如果进程A抢到了锁L,那么在进程A释放锁之前,进程B和C是无法再加锁成功的。如果A进程抢锁成功是通过线程A1,那么当线程A2、A3、...再执行抢锁L的操作时,依然会返回加锁成功;如果是由线程An抢到的锁L,可以由线程Ax来释放锁L。

  使用以上3个函数实现的读写锁的效果和互斥锁的效果,在多线程中是一致的,在此不再赘述。

   总之:以上3个函数lockf()、fcntl()、flock()实现的互斥锁、读写锁的作用域是进程级的,这种锁不能用来保证多线程中数据的安全性和一致性。

以上是关于Linux下各种编程锁的比较[待续]的主要内容,如果未能解决你的问题,请参考以下文章

Linux下各种锁的理解和使用及总结解决epoll惊群问题(面试常考)

iOS各种锁的比较

Java6中对synchronized的优化

JAVA8-待续

分治思想01_排序算法_归并_各种写法和思路(待续)

Java多线程并发编程/锁的理解