golang下文件锁的使用[通俗易懂]

golang下文件锁的使用[通俗易懂]前言题目是golang下文件锁的使用,但本文的目的其实是通过golang下的文件锁的使用方法,来一窥文件锁背后的机制。为什么需要文件锁只有多线程/多进程这种并发场景下读写文件,才需要加锁,场景1-读写并发读写并发场景下,如果不加锁,就会出现读到脏数据的情况。想象一下,读文件的进程,读到第500字节,有其它进程以覆盖写的方式向文件中写入1000字节,那读进程读到的后500字节就是脏数据。场景2-写写并发写写并发场景下,如果不加锁,假设A进程先写0-1000字节,B进程写0-900字节,以此类

大家好,又见面了,我是你们的朋友全栈君。

前言

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

为什么需要文件锁

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

场景1-读写并发

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

场景2-写写并发

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

文件锁的几个概念

共享锁

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

排它锁

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

阻塞

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

非阻塞

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

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

golang下如何使用文件锁

基本使用


package main

import (
    "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

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/153498.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 2022年最新前端面试题,持续更新「建议收藏」

    2022年最新前端面试题,持续更新「建议收藏」2022年最新前端面试题适合初/中级前端开发工程师

    2022年10月17日
    3
  • 真正解决Jenkins安装插件总是报错的问题(二)

    真正解决Jenkins安装插件总是报错的问题(二)

    2021年8月31日
    61
  • windows错误恢复如何解决_0xc0000006是什么错误

    windows错误恢复如何解决_0xc0000006是什么错误0xc0000005三种不同的情况下会发生错误常见原因修复访问错误解决方案1:停用程序的数据执行保护(DEP)解决方案2:在Windows注册表中停用AppInit_DLLs机制解决方案3:执行恶意软件扫描解决方案4:运行Windows内存诊断程序并替换任何有缺陷的RAM启动应用程序时如何解决0xc0000005错误解决方案1:更新设备驱动程序解决方案2:修复BCD文件安装Windows时出现0xc0000005错误:最佳解决方案解决方案1:删除并重新创建Windows硬盘分区解决方案2:更换有缺陷的硬件

    2022年10月4日
    3
  • 最速下降法收敛速度快还是慢_最速下降法是全局收敛算法吗

    最速下降法收敛速度快还是慢_最速下降法是全局收敛算法吗\qquad已知设步长为α\alphaα,下降方向为ddd,f(xk+αd)f(x_{k}+\alphad)f(xk​+αd)在xkx_{k}xk​的TaylorTaylorTaylor展示为f(xk+1)=f(xk+αd)=f(xk)+αgkTd+O(∣∣αd∣∣2)f(x_{k+1})=f(x_{k}+\alphad)=f(x_{k})+\alphag_{k}^{T}d+O(||\…

    2025年6月3日
    5
  • poe交换机和普通交换机区别_交换机可以接交换机吗

    poe交换机和普通交换机区别_交换机可以接交换机吗一个完整的POE系统包括供电端设备(PSE,PowerSourcingEquipment)和受电端设备(PD,PowerDevice)两部分,POE交换机为PSE设备的一种。PSE设备是为以太网客户端设备供电的设备,同时也是整个POE以太网供电过程的管理者。而PD设备是接受供电的PSE负载,即POE系统的客户端。POE交换机和普通交换机哪里不同?POE交换机和普通交换机有什么不同,P…

    2022年10月5日
    2
  • LCD1602液晶使用介绍–(完整版)

    LCD1602液晶使用介绍–(完整版)lcd1602+c51介绍文章目录LCD1602介绍1602引脚信号说明控制器接口介绍1、基本操作时许2、状态字说明3、指令说明RAM地址映射控制时序图代码实现写入命令写数据试验例程CGRAM自定义字模(简易汉字显示)LCD1602介绍LCD1602液晶在实际的产品运用中也是比较多产品,应为前一段时间也正好用到了所以惊天就对LCD1602液晶做一个总结,方便以后阅读同时也希望能够帮住到需要的人,总结的可能存在错误欢迎指出!所谓的1602是指显示的时候,有2行内容每行有16个字符。其实这类字符型产

    2022年7月16日
    14

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号