前言

题目是golang下文件锁的使用,但本文的目的其实是通过golang下的文件锁的使用方法,来一窥文件锁背后的机制。

为什么需要文件锁

只有多线程/多进程这种并发场景下读写文件,才需要加锁,

场景1-读写并发

读写并发场景下,如果不加锁,就会出现读到脏数据的情况。想象一下,读文件的进程,读到第500字节,有其它进程以覆盖写的方式向文件中写入1000字节,那读进程读到的后500字节就是脏数据。

场景2-写写并发

写写并发场景下,如果不加锁,假设A进程先写0-1000字节,B进程写0-900字节,以此类推,最后一个进程写0-100字节,那最终的文件内容就是每个进程前100个字节拼接起来的错乱的内容了。

文件锁的几个概念

共享锁

共享锁,也叫读锁。某个进程首次获取共享锁后,会生成一个锁类型的变量L,类型标记为共享锁。其它进程获取读锁的时候,L中的计数器加1,表示又有一个进程获取到了共享锁。这个时候如果有进程来获取排它锁,会获取失败。

排它锁

排它锁,也叫写锁。某个进程首次获取排他锁后,会生成一个锁类型的变量L,类型标记为排他锁。其它进程获取任何类型的锁的时候,都会获取失败。

阻塞

阻塞的意思是说,新的进程发现当前的文件(数据)被加锁后,会一直处于等待状态,直到锁被释放,才会继续下一步的行为。

非阻塞

非阻塞的意思是说,新的进程发现当前的文件(数据)被加锁后,立即返回异常。业务上需要根据具体的业务场景对该异常进行处理。

阻塞和非阻塞其实是进程遇到锁的时候的两种处理模式。

golang下如何使用文件锁

基本使用


package mainimport ("log""os""syscall"
)func main() {f, err := os.Create("example.txt")if err != nil {log.Println("create file example.txt failed", err)}defer f.Close()// 非阻塞模式下,加共享锁if err := syscall.Flock(int(f.Fd()), syscall.LOCK_SH|syscall.LOCK_NB); err != nil {log.Println("add share lock in no block failed", err)}// 这里进行业务逻辑// TODO// 解锁if err := syscall.Flock(int(f.Fd()), syscall.LOCK_UN); err != nil {log.Println("unlock share lock failed", err)}return
}

示例中 LOCK_SH 表示当前获取的是共享锁,如果是 LOCK_EX,则表示获取的是排他锁。而 LOCK_NB 表示当前获取锁的模式是非阻塞模式,如果需要阻塞模式,不加这个参数即可。LOCK_UN 则表示解锁,即释放锁。

golang 下这种文件锁的使用方式其实是Linux下的系统级调用,使用的是Linux的原生的文件锁的相关能力。

使用flock的几个注意点

1、只要fd指向的是同一个文件指针,那么加锁解锁的行为都是继承和覆盖的(这个可以看最后的解释)。

2、flock这种方式加的是建议性锁,也就是说新的进程一上来不管三七二十一,不去通过flock获取锁,就对文件各种操作,也是可以正常生效的。

说一说Linux下面的flock和fcntl

和flock一样,fcntl也是系统级调用,但是在具体的使用上却有很大不用,并且两种锁互不干扰,用flock加锁,fcntl无法感知,反之也一样。

建议性锁和强制锁

flock加的是建议性锁,而fcntl加的是强制性锁。

建议性锁,本质是一种协议,约定读写操作前都去检查一下该文件是否有被其它进程加锁。如果不遵守该协议,一上来就对文件进行操作,不检查有没有锁,程序执行上是没有任何问题的,能执行成功。

强制性锁,才更像真正意义上的锁。只要加了锁,其它进程是无法执行非允许的操作的。

其实一些利用redis做的分布式锁,都是建议性锁。锁机的机制要生效,需要大家共同遵守这个约定才行。

全局锁和局部锁

对于一个文件,flock加锁的范围是整个文件内容,而fcntl能对文件的任意部分加锁。

锁的持有者问题

flock认为,锁的持有者是文件表(可以理解为文件指针),所以对于fork和dup操作,他们都对应同一个文件指针,所有的操作都会作用到这个文件上。具体表现:

  • A进程加锁,A的子进程进程可以解锁,新的操作会覆盖之前的操作
  • A进程加锁,A进程复制fd,仍然是可以通过新的fd操作文件锁,新的操作会覆盖之前的操作

fcntl 认为,锁的持有者是进程。加锁和解锁的行为都是跟着进程走,具体表现为:

  • A进程加锁,B进程得等A进程消亡或者解锁才能加锁

参考

[1] 被遗忘的桃源——flock 文件锁

[2] Linux文件锁学习-flock, lockf, fcntl

原创不易,欢迎关注我的公众号:码农的自由之路

golang下文件锁的使用相关推荐

  1. Golang下的Log处理

    Golang下的Log处理 原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com 后端系统中的Log是相当重要的,做过高并发服务的同学都会认同这一点.相对而言,调试已经 ...

  2. golang 下划线

    1.下划线在import中 在Golang里,import的作用是导入其他package,但是今天在看beego框架时看到了import 下划线,不知其意,故百度而解之. import 下划线(如:i ...

  3. golang下的条件编译

    本文转自  使用go build 进行条件编译 http://blog.csdn.net/varding/article/details/12675971 当我们编写的Go代码依赖特定平台或者cpu架 ...

  4. windows下golang监控鼠标和键盘事件

    最近一直在研究golang下监听键盘和鼠标的操作事件功能, github上有也有非常优秀的开源库robotgo, 它地址如下, 有兴趣的同学可以去研究下: https://github.com/go- ...

  5. Golang websocket

    2019独角兽企业重金招聘Python工程师标准>>> 环境:Win10 + Go1.9.2 1.先下载并引用golang的websocket库 ①golang的官方库都在https ...

  6. 【Golang 基础】Go 语言的程序结构

    Go 语言的项目结构    一般,一个 Go 项目在 GOPATH 下,会有如下三个目录 . ├── bin // 存放编译后的可执行文件 ├── pkg // 存放编译后的包文件 └── src / ...

  7. golang执行多个linux命令,golang执行系统command

    golang下的os/exec包执行外部命令,它将os.StartProcess进行包装使得它更容易映射到stdin和stdout.这点和python下的command.os.system等功能是一样 ...

  8. 安利一个好用的Golang单元测试框架:gocheck

    Golang下如何写单元测试?官方提供的testing package略显简陋,不过好在我们有Gocheck. 什么是好的单元测试? 在进入正题前,先来温习下前人总结的单元测试几条原则: http:/ ...

  9. 【死磕NIO】— 跨进程文件锁:FileLock

    大家好,我是大明哥,一个专注于[死磕 Java]系列创作的程序员. [死磕 Java ]系列为作者「chenssy」 倾情打造的 Java 系列文章,深入分析 Java 相关技术核心原理及源码 死磕 ...

最新文章

  1. 磁盘配额的wmi版本(C#)
  2. 脏读和数据库一致性的分析
  3. PMcff 020产品经理峰会现场火爆,干货不断
  4. Winform中使用FastReport实现自定义PDF打印预览
  5. [编写高质量代码:改善java程序的151个建议]建议31-在接口中不要存在实现代码...
  6. git 修改分支名字_基础Git操作与GitHub协作吐血整理,收好!| 原力计划
  7. [CityLife]“背后的故事”---贫嘴曾志伟
  8. Ballast,一种精准控制 Go GC 提高性能的方法
  9. 启动tomcat后无法访问
  10. G-SYNC技术是什么
  11. 一个java内存泄漏的排查案例
  12. 【Web API系列教程】3.10 — 实战:处理数据(公布App到Azure App Service)
  13. 基于51单片机的智能温控风扇设计
  14. premiere学习笔记01帧定格,时间码,透明视频,调整图层,转场及批量转场,插件安装,音频调整,关键帧,马赛克,蒙版,嵌套序列
  15. 计算机电脑基础程序,电脑程序入门知识
  16. web控件安装问题解决办法
  17. 在电脑中怎样画思维导图
  18. CRAFTS:端对端的场景文本检测器
  19. IROS2020 论文阅读
  20. 调试程序基本步骤方法

热门文章

  1. python高级教程_Python高级进阶教程
  2. 自定义审批流程表设计
  3. ubuntu18.04 编译rtt-lwr
  4. Mac剪切AVI视频
  5. android support v13,java – 程序类型已存在:android.support.v13.v...
  6. 程序员分哪几种?分别要学什么知识?工资怎么样?
  7. C语言atoi、atol、atoll和atoq函数
  8. 【报错】Cannot uninstall ‘certifi‘. It is a distutils installed project and thus we cannot accurately
  9. 这些API接口,随便拿出来一个就能装逼、赚钱
  10. 精密仪器及机械类毕业论文文献包含哪些?