写了一个简单的 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
1 ho121 2020-10-11 18:42:24 +08:00 via Android fwrite 执行之前被其它线程 fseek 改掉了位置 |
2 qianlv7 2020-10-11 18:44:12 +08:00 用 pwrite,FILE* 共享了位移 |
3 qianlv7 2020-10-11 18:45:13 +08:00 文件偏移共享了,导致冲突 |
![]() | 5 geelaw 2020-10-11 18:58:19 +08:00 ![]() @1YsX1 #4 这是双重理解错误。 1. FILE * 实际起效果的是“被指向的” FILE 结构,而不是 FILE * 本身,复制指针的值并不会复制 FILE 结构,因此操作的是同一个 FILE 。 2. fseek 传入的参数是 FILE * 而不是 FILE *&,并不存在“操作传入的变量”这种说法,它获得的永远是传入值的副本。把 fp 复制到 nowfp 再传入是多此一举,不会有任何效果。 |
![]() | 6 9LCRwvU14033RHJo 2020-10-11 19:04:07 +08:00 FILE 里面有文件描述符。文件描述符只是一个数组下标而已。数组“打开文件表”是操作系统维护的,所有进程共享的。 |
9 abutter 2020-10-12 08:39:09 +08:00 man 2 flock |
![]() | 10 jedihy 2020-10-12 09:52:43 +08:00 哈哈,楼主是不是原来写 js 的? |
11 Testlinuxtous 2020-10-24 03:34:48 +08:00 via iPhone @abutter 能给一个邮箱交流一下吗? |
12 UFc8704I4Bv63gy2 2020-12-02 00:53:12 +08:00 via Android 加锁,这个问题在 win 上应该不存在,在 unix 系统上肯定有 |