请教一个简单的 C++并发文件写入冲突的问题。

2020-10-11 18:31:12 +08:00
 1YsX1

写了一个简单的 demo 来测试单文件的并发写入,给每个位置写且仅写一次不同的数字,我觉得这个场景貌似是不包含冲突的问题的,因为访问的文件地址都不一样的。但是实际结果确实是产生冲突了。希望有大佬有时间进行指教,谢谢!
代码如下

#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <stdint.h>

using namespace std;

FILE *fp;

void * running(void * args){
    uint8_t* pos = (uint8_t *)args;
    FILE * nowfp = fp;
    fseek(nowfp,*pos,SEEK_SET);
    fwrite(pos,1,1,nowfp);
    delete pos;
    return 0;
}

int main(int,char **){
    fp = fopen("test.bin","wb+");
    pthread_t t_a;
    for(int i =0;i<100;i++){
        uint8_t* j = new uint8_t(i);
	    pthread_create(&t_a,NULL,running,j);
    }
    while (true)
    {
        sleep(1000);
    }
    return 0;
}

程序输出结果如下 除了第一个位置以外,有很多值为 0 的点。不太明白这个并发冲突产生在哪里。:

  Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 	
00000000: 00 00 02 03 01 00 00 07 08 04 0A 0B 0C 0D 0E 0F    ................
00000010: 10 11 12 13 2F 15 16 17 18 19 1A 1B 00 1D 1E 1F    ..../...........
00000020: 20 21 22 23 00 25 26 40 28 00 2A 2B 2C 2D 2E 00    .!"#.%&@(.*+,-..
00000030: 30 31 32 33 34 35 36 37 00 39 3A 3B 00 3D 3E 3F    01234567.9:;.=>?
00000040: 00 41 42 43 44 45 46 47 3C 48 00 4B 4C 4D 4E 4F    .ABCDEFG<H.KLMNO
00000050: 50 51 52 53 54 55 56 57 58 59 00 5B 5C 5D 5E 5F    PQRSTUVWXY.[\]^_
00000060: 60 61 62 63                                        `abc

2611 次点击
所在节点    C++
12 条回复
ho121
2020-10-11 18:42:24 +08:00
fwrite 执行之前被其它线程 fseek 改掉了位置
qianlv7
2020-10-11 18:44:12 +08:00
用 pwrite,FILE* 共享了位移
qianlv7
2020-10-11 18:45:13 +08:00
文件偏移共享了,导致冲突
1YsX1
2020-10-11 18:53:07 +08:00
@ho121
@qianlv7
fseek 操作的是一个临时变量 nowfp 而不是全局变量 fp,这样也会有冲突??
geelaw
2020-10-11 18:58:19 +08:00
@1YsX1 #4 这是双重理解错误。

1. FILE * 实际起效果的是“被指向的” FILE 结构,而不是 FILE * 本身,复制指针的值并不会复制 FILE 结构,因此操作的是同一个 FILE 。
2. fseek 传入的参数是 FILE * 而不是 FILE *&,并不存在“操作传入的变量”这种说法,它获得的永远是传入值的副本。把 fp 复制到 nowfp 再传入是多此一举,不会有任何效果。
user8341
2020-10-11 19:04:07 +08:00
FILE 里面有文件描述符。文件描述符只是一个数组下标而已。数组“打开文件表”是操作系统维护的,所有进程共享的。
ho121
2020-10-11 19:21:35 +08:00
@1YsX1 变量是不同的,但它们指向的对象是一个对象(指针地址一样)
1YsX1
2020-10-11 20:08:35 +08:00
@geelaw
@user8341
@ho121
谢谢各位的指点!我明白了!!
abutter
2020-10-12 08:39:09 +08:00
man 2 flock
jedihy
2020-10-12 09:52:43 +08:00
哈哈,楼主是不是原来写 js 的?
Testlinuxtous
2020-10-24 03:34:48 +08:00
@abutter 能给一个邮箱交流一下吗?
weiqk
2020-12-02 00:53:12 +08:00
加锁,这个问题在 win 上应该不存在,在 unix 系统上肯定有

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/713956

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX