std::mutex必须锁住整个写入操作(含格式化、write()和flush),而非仅operator<<;否则因流内部多步执行仍会乱序。正确做法是先拼好完整字符串,再用lock_guard包裹file << str和必要flush。

直接用多个 std::ofstream 实例并发写同一个文件,必然出错——不是“可能丢数据”,而是“一定乱序、截断、崩溃”。标准库流对象本身不线程安全,底层 write() 调用也非原子,更别说缓冲区、文件偏移、seek() 位置全在裸奔。
std::mutex 怎么锁才真正生效
只锁 operator 或 <code>write() 调用是无效的。因为 std::ofstream 内部有缓冲,flush() 可能在锁作用域外触发,实际写入仍会并发。
- 必须关闭缓冲:
log_file.rdbuf()->pubsetbuf(nullptr, 0),让每次写都直通系统调用 - 所有写操作(格式化 +
write()+ 换行)必须包裹在同一个std::mutex临界区内 - 不能每个线程 new 一个
std::ofstream再 lock——析构时自动close()会导致其他线程后续写失败 - 推荐全局单例
std::ofstream+ 全局std::mutex,初始化在主线程完成
std::ios::app 模式是不是就安全了
不安全。std::ios::app 只保证每次 write() 前 seek 到 EOF,但 “seek → write” 是两步,中间完全可能被其他线程插入。
- 即使所有线程都用
std::ios::out | std::ios::app打开同一路径,仍会竞争文件偏移量 - Windows 下可能直接报
ERROR_SHARING_VIOLATION - Linux 下虽允许打开,但数据完整性无任何保障
- 真正安全的 append 行为,只能靠 mutex 强制串行化写入逻辑,而不是依赖流模式
flock() 或 LockFileEx() 能替代 mutex 吗
不能直接替代,且容易误用。它们和 std::ofstream 不在一个抽象层。
立即学习“C++免费学习笔记(深入)”;
-
flock()作用于文件描述符,你得先用open()或CreateFileA()获取 fd/handle,再手动write(),完全绕过 C++ 流的缓冲与格式化能力 - 它只是建议性锁(advisory),所有写入方必须主动参与加锁,漏一个就失效
- 它无法防止单次
write()被内核切片——POSIX 只保证小于 PIPE_BUF 的写是原子的,但日志行若超长仍可能被截断 - 如果坚持用系统级文件锁,必须确保:每次写前
flock(fd, LOCK_EX),写完立即flock(fd, LOCK_UN),且锁粒度覆盖从字符串格式化到write()完成的全过程
最易被忽略的一点:日志行必须以完整字符串(含 \n)为单位写入。分多次 << "msg" << time << "\n" 即使加了锁,也会因流内部状态变化导致行为不可控;应先拼好整个字符串,再单次写入。



















