golang文件锁,目录锁,syscall包的使用
先说结论
1. golang提供了syscall包来实现文件/目录的加锁,解锁
2. syscall包属于文件锁,是比较底层的技术,并不能在所有操作系统上完全实现,linux上实现了,windows下面就没有
3. 加锁时调用syscall.Flock(fd,syscall.LOCK_EX),解锁时调用syscall.Flock(fd, syscall.LOCK_UN)
4. 加锁成功后,对加锁的文件fd进行Close()操作同样会释放锁,切记
代码实现
锁的定义如下内部两个变量:文件/目录的全路径名,文件对象
// 文件锁/目录锁
type DirLock struct {
dir string // 文件/目录的全路径名
f *os.File // 文件对象
}
加锁的实现
核心代码是 syscall.Flock(int(f.Fd()), LOCK_EX|syscall.LOCK_NB),注意其中的标记
LOCK_EX :加锁标记。只有一个进程能加锁成功,其他进程再尝试加锁时会阻塞,等同于我们常用的写锁
LOCK_NB :不阻塞标记。如果其他进程已加锁成功,自己去尝试加锁时就不再阻塞,而是直接返回错误
// 加锁
func (l *DirLock) Lock() error {
f, err := os.Open(l.dir)
if err != nil {
return err
}
l.f = ferr = syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
if err != nil {
return err
}
return nil
}
解锁的实现
核心代码是 syscall.Flock(int(l.f.Fd()), syscall.LOCK_UN)
LOCK_UN :解锁标记。如果自己已经加锁成功,可以用此标记去解锁
// 解锁
func (l *DirLock) Unlock() error {
defer l.f.Close() // 关闭文件return syscall.Flock(int(l.f.Fd()), syscall.LOCK_UN) // LOCK_UN表解锁
}
实验
我们建立5个协程,每秒去尝试加锁一次,失败则1秒后重试,成功则持续2秒后解锁
核心代码如下
// 5个协程,都尝试对目录加锁,加锁失败的就重试,加锁成功的2秒后释放
for i := 0; i < 5; i++ {
wg.Add(1)go func(num int) {
dirLock := New(dir)
ticker := time.NewTicker(time.Second) // 定时器每秒尝试1次
for {
select {
case <-ticker.C:
{
err := dirLock.Lock() // 加锁尝试
if err != nil {
fmt.Printf("lock dir failed, goroutine num=%d, err=%s \n", num, err.Error())
continue
}
fmt.Println("lock dir succeed, goroutine num=", num)
goto end
}
}
}end:
time.Sleep(time.Second*2)
dirLock.Unlock() // 解锁
wg.Done()
}(i)
}
wg.Wait()
实验结果如下图

完整代码
package main
import ("fmt""os""sync""syscall""time"
)// 目录锁
type DirLock struct {dir string // 目录的全路径名f *os.File // 文件对象
}func New(dir string) *DirLock {return &DirLock{dir: dir,}
}// 加锁
func (l *DirLock) Lock() error {f, err := os.Open(l.dir)if err != nil {return err}l.f = ferr = syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)if err != nil {return err}return nil
}// 释放锁
func (l *DirLock) Unlock() error {defer l.f.Close() // 其实不执行Close()也会释放目录锁return syscall.Flock(int(l.f.Fd()), syscall.LOCK_UN)
}func main() {dir, _ := os.Getwd()wg := sync.WaitGroup{}// 5个协程,都尝试对目录加锁,加锁失败的就重试,加锁成功的2秒后释放for i := 0; i < 5; i++ {wg.Add(1)go func(num int) {dirLock := New(dir)ticker := time.NewTicker(time.Second) // 定时器每秒尝试1次for {select {case <-ticker.C:{err := dirLock.Lock() // 加锁尝试if err != nil {fmt.Printf("lock dir failed, goroutine num=%d, err=%s \n", num, err.Error())continue}fmt.Println("lock dir succeed, goroutine num=", num)goto end}}}end:time.Sleep(time.Second*2)dirLock.Unlock() // 解锁wg.Done()}(i)}wg.Wait()
}相关文章:
golang文件锁,目录锁,syscall包的使用
先说结论 1. golang提供了syscall包来实现文件/目录的加锁,解锁 2. syscall包属于文件锁,是比较底层的技术,并不能在所有操作系统上完全实现,linux上实现了,windows下面就没有 3. 加锁时调用syscall.Flock(fd&#…...
数据库数据恢复-Syabse数据库存储页底层数据杂乱的数据恢复案例
数据库恢复环境: Sybase版本:SQL Anywhere 8.0。 数据库故障: 数据库所在的设备意外断电后,数据库无法启动。 错误提示: 使用Sybase Central连接后报错: 数据库故障分析: 经过北亚企安数据恢复…...
移远通信推出新一代高算力智能模组SG885G-WF,为工业和消费级IoT应用带来全新性能标杆
2023年7月24日,全球领先的物联网整体解决方案供应商移远通信宣布,正式推出其新一代旗舰级安卓智能模组SG885G-WF。该智能模组具有高达48 TOPS 的AI综合算力、强大性能及丰富的多媒体功能,非常适用于需要高处理能力和多媒体功能的工业和消费者…...
微信小程序开发,小程序类目符合,线上版本无权限申请wx.getLocation接口
我开发 的小程序类目符合wx.getLocation接口的申请标准 但是却还是显示无权限申请 后来研究好久才发现,小程序需要在发布线上版本时提交用户隐私保护指引 如未设置也可以在 设置-服务内容声明-用户隐私保护指引-声明处理用户信息项并补充填写后提交用户隐私协议审核…...
vue2企业级项目(五)
vue2企业级项目(五) 页面适配、主题切换 1、适配 项目下载插件 npm install --save-dev style-resources-loader vue-cli-plugin-style-resources-loader修改vue.config.js部分内容 const path require("path");module.exports {pluginOpt…...
【HTML5】拖放详解及实现案例
文章目录 效果预览代码实现 效果预览 代码实现 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>一颗不甘坠落的流星</title><style>#div1,#div2 {float: left;width: 100px;height: 27px;margin: 10px;paddin…...
Codeforces Round 888 (Div. 3)(视频讲解全部题目)
[TOC](Codeforces Round 888 (Div. 3)(视频讲解全部题目)) Codeforces Round 888 (Div. 3)(A–G)全部题目详解 A Escalator Conversations #include<bits/stdc.h> #define endl \n #define INF 0x3f3f3f3f using namesp…...
MySQL之深入InnoDB存储引擎——物理文件
文章目录 一、参数文件二、日志文件三、表结构定义文件四、InnoDB 存储引擎文件1、表空间文件2、重做日志文件 一、参数文件 当 MySQL 实例启动时,数据库会先去读一个配置参数文件,用来寻找数据库的各种文件所在位置以及指定某些初始化参数。在默认情况…...
Jquery操作html常用函数
1. text() 获取元素的文本内容:$("#element").text(); 设置元素的文本内容:$("#element").text("New Text"); 2. html() 获取元素的 HTML 内容:$("#element").html(); 设置元素的 HTML 内容&am…...
【Lua学习笔记】Lua进阶——Table,迭代器
文章目录 官方唯一指定数据结构--tabletable的一万种用法字典和数组 迭代器ipairs()pairs() 回到Table 在【Lua学习笔记】Lua入门中我们讲到了Lua的一些入门知识点,本文将补充Lua的一些进阶知识 官方唯一指定数据结构–table 在上篇文章的最后,我们指出…...
重庆市北斗新型智慧城市政府项目
技术栈:使用vue2JavaScriptElementUIvuexaxiosmapboxcesium 项目描述:重庆市北斗新型智慧城市政府项目是基于千寻孪界开发的一款智慧城市项目,包含车辆实时位置定位,智能设备的报警,基础设施的部设等等功能 工作内容&a…...
FANUC机器人SRVO-217故障报警原因分析及参考解决办法
FANUC机器人SRVO-217故障报警原因分析及参考解决办法 如下图所示,示教器提示:SRVO-217紧急停止电路板未找到, 查阅手册可以看到以下的报警说明: 故障原因: 通电时未能识别紧急停止电路板或者增设的安全I/O装置。连接有多个安全I/O装置的系统中,在报警信息的最后,会显示发…...
统信UOS安装mysql数据库(mariadb)-统信UOS安装JDK-统信UOS安装nginx(附安装包)
统信UOS离线全套安装教程(手把手教程) 银河麒麟的各种离线全套安装教程: https://blog.csdn.net/ACCPluzhiqi/article/details/131988147 1.统信UOS桌面系统安装mysql(mariadb) 2.统信UOS桌面系统安装JDK 3.统信UOS桌…...
上门小程序开发|上门服务小程序|上门家政小程序开发
随着移动互联网的普及和发展,上门服务成为了许多人生活中的一部分。上门小程序是一种基于小程序平台的应用程序,它提供了上门服务的在线平台,为用户提供了便捷的上门服务体验。下面将介绍一些适合开发上门小程序的商家。 家政服务商家&am…...
1000道网络安全必备面试题合集,秋招金九银十必看!!!
以下为网络安全各个方向涉及的面试题,星数越多代表问题出现的几率越大,祝各位都能找到满意的工作。 注:本套面试题,已整理成pdf文档,但内容还在持续更新中,因为无论如何都不可能覆盖所有的面试问题&#x…...
从0-1实现简易Raft分布式共识算法
一、Raft前置简介 Raft目前是最著名的分布式共识性算法,被广泛的应用在各种分布式框架、组件中,如Redis、RocketMq、Kafka、Nacos(CP)等 根据Raft论文,可将Raft拆分为如下4个功能模块: 领导者选举日志同…...
Spring 创建和使用
Spring 是⼀个包含了众多⼯具⽅法的 IoC 容器。既然是容器那么它就具备两个最基本的功能: 将对象存储到容器(Spring)中; 从容器中将对象取出来。 在 Java 语⾔中对象也叫做 Bean 1.创建 Spring 项目 接下来使⽤ Maven ⽅式来创…...
Javadoc comment自动生成
光标放在第二行 按下Alt Shift j 下面是Java doc的生成 Next Next-> Finish...
vue3 +ts 报错 index.vue 不是模块
那是因为index.vue中创建了一个空的script标签,而且语法使用的是ts语法。vue-cli会用ts语法解析和校验 如果是无状态组件,删掉 如果是有状态组件,导出该组件的实例 去掉null的script后:...
win10 hadoop报错 unable to load native-hadoop library
win10 安装hadoop执行hdfs -namenode format 和运行hadoop的start-all报错 unable to load native-hadoop library 验证: hadoop checknative -a 这个命令返回都是false是错的 返回下图是正确的 winutils: true D:\soft\hadoop-3.0.0\bin\winutils.exe Native li…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
