c++如何实现文件锁定防止并发修改_flock与LockFile怎么用

来源:站长站作者:比特币程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《c++如何实现文件锁定防止并发修改_flock与LockFile怎么用》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《c++如何实现文件锁定防止并发修改_flock与LockFile怎么用》有用,将其分享出去将是对创作者最好的鼓励。

在c++多进程或多线程的开发场景中,多个执行流同时读写同一个文件时,很容易出现数据覆盖、内容错乱的问题,文件锁定是解决这类并发修改问题的有效手段。不同操作系统提供了不同的文件锁定接口,Linux系统常用flock函数,Windows系统常用LockFile函数,下面分别介绍两种方式的实现方法。

c++如何实现文件锁定防止并发修改_flock与LockFile怎么用

Linux系统下使用flock实现文件锁定

flock是Linux系统提供的文件锁定系统调用,作用是对打开的文件描述符施加建议性锁,锁的粒度是整个文件,使用起来比较简单。

flock函数原型

flock的函数定义在<sys/file.h>头文件中,原型如下:

#include <sys/file.h>
int flock(int fd, int operation);

参数说明:

  • fd:已经打开的文件描述符,需要通过open函数先打开目标文件获取
  • operation:锁的操作类型,可选值如下:
    • LOCK_SH:施加共享锁,多个进程可以同时持有共享锁,适合读操作场景
    • LOCK_EX:施加排他锁,同一时间只能有一个进程持有排他锁,适合写操作场景
    • LOCK_UN:释放锁
    • LOCK_NB:非阻塞模式,和上述三种操作按位或组合使用,获取锁失败时直接返回不阻塞

返回值:成功返回0,失败返回-1并设置errno。

flock使用示例

下面是一个使用flock实现写文件时加排他锁的完整示例:

#include <iostream>
#include <fcntl.h>
#include <sys/file.h>
#include <unistd.h>
#include <string.h>

int main() {
    // 打开目标文件,不存在则创建,权限为0644
    int fd = open("test.txt", O_RDWR | O_CREAT, 0644);
    if (fd == -1) {
        std::cerr << "打开文件失败" << std::endl;
        return 1;
    }

    // 施加排他锁,阻塞模式等待锁释放
    if (flock(fd, LOCK_EX) == -1) {
        std::cerr << "加锁失败" << std::endl;
        close(fd);
        return 1;
    }

    std::cout << "获取排他锁成功,开始写入文件" << std::endl;
    // 执行文件写入操作
    const char* content = "这是并发安全的写入内容n";
    write(fd, content, strlen(content));

    // 模拟业务处理耗时
    sleep(5);

    // 释放锁
    flock(fd, LOCK_UN);
    std::cout << "写入完成,锁已释放" << std::endl;

    close(fd);
    return 0;
}

注意事项:flock施加的是建议性锁,也就是说如果其他进程不调用flock尝试加锁,直接操作文件依然可以修改内容,所以所有操作文件的进程都需要遵循加锁的规则才能保证效果。另外flock的锁在进程退出时会自动释放,不需要手动释放也可以避免死锁。

Windows系统下使用LockFile实现文件锁定

Windows系统没有提供flock接口,对应的文件锁定函数是LockFile,属于Windows API的一部分,需要包含<windows.h>头文件,锁的粒度可以指定文件的偏移量和长度,比flock更灵活。

LockFile函数原型

LockFile的函数原型如下:

BOOL LockFile(
  HANDLE hFile,
  DWORD   dwFileOffsetLow,
  DWORD   dwFileOffsetHigh,
  DWORD   nNumberOfBytesToLockLow,
  DWORD   nNumberOfBytesToLockHigh
);

参数说明:

  • hFile:打开的文件句柄,通过CreateFile函数获取
  • dwFileOffsetLow:锁定区域起始偏移量的低32位
  • dwFileOffsetHigh:锁定区域起始偏移量的高32位,通常设置为0即可
  • nNumberOfBytesToLockLow:锁定区域长度的低32位
  • nNumberOfBytesToLockHigh:锁定区域长度的高32位,通常设置为0即可

返回值:成功返回非零值,失败返回0,可以通过GetLastError获取错误原因。对应的解锁函数是UnlockFile,参数和LockFile完全一致。

LockFile使用示例

下面是一个使用LockFile实现文件锁定的完整示例:

#include <iostream>
#include <windows.h>

int main() {
    // 打开目标文件,不存在则创建
    HANDLE hFile = CreateFile(
        "test.txt",
        GENERIC_READ | GENERIC_WRITE,
        0, // 不共享,其他进程无法同时打开该文件
        NULL,
        OPEN_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL
    );
    if (hFile == INVALID_HANDLE_VALUE) {
        std::cerr << "打开文件失败,错误码:" << GetLastError() << std::endl;
        return 1;
    }

    // 锁定整个文件,偏移量0,长度0xFFFFFFFF表示锁定到文件末尾
    if (LockFile(hFile, 0, 0, 0xFFFFFFFF, 0) == 0) {
        std::cerr << "加锁失败,错误码:" << GetLastError() << std::endl;
        CloseHandle(hFile);
        return 1;
    }

    std::cout << "获取文件锁成功,开始写入文件" << std::endl;
    // 执行文件写入操作
    const char* content = "这是Windows下并发安全的写入内容n";
    DWORD bytesWritten;
    WriteFile(hFile, content, strlen(content), &bytesWritten, NULL);

    // 模拟业务处理耗时
    Sleep(5000);

    // 解锁文件
    UnlockFile(hFile, 0, 0, 0xFFFFFFFF, 0);
    std::cout << "写入完成,锁已释放" << std::endl;

    CloseHandle(hFile);
    return 0;
}

注意事项:LockFile施加的是强制锁,只要文件被锁定,其他进程即使不调用LockFile也无法修改被锁定的区域。另外LockFile的锁不会随进程退出自动释放,如果进程异常退出没有调用UnlockFile,锁会一直存在,所以需要在代码中做好异常处理,确保锁能被正常释放。

两种方式对比与选择建议

两种方式的核心差异如下:

对比项flockLockFile
适用系统Linux/Unix类系统Windows系统
锁粒度整个文件可指定文件区域
锁类型建议性锁强制性锁
自动释放进程退出自动释放需要手动调用UnlockFile释放

选择建议:如果是Linux平台开发优先使用flock,实现简单且不需要手动处理锁释放;如果是Windows平台开发使用LockFile,注意做好异常场景下的锁释放逻辑。如果是跨平台项目,可以通过条件编译区分不同系统的实现,保证文件锁定的兼容性。

flockLockFile文件锁定并发修改修改时间:2026-07-16 03:42:32

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。