写了一个简单的 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 1
@1YsX1 #4 这是双重理解错误。
1. FILE * 实际起效果的是“被指向的” FILE 结构,而不是 FILE * 本身,复制指针的值并不会复制 FILE 结构,因此操作的是同一个 FILE 。 2. fseek 传入的参数是 FILE * 而不是 FILE *&,并不存在“操作传入的变量”这种说法,它获得的永远是传入值的副本。把 fp 复制到 nowfp 再传入是多此一举,不会有任何效果。 |
6
user8341 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
weiqk 2020-12-02 00:53:12 +08:00 via Android
加锁,这个问题在 win 上应该不存在,在 unix 系统上肯定有
|