我们是否需要互斥量来执行多线程文件 IO
Do we need mutex to perform multithreading file IO
我正在尝试使用多线程 (pthread) 对文件进行随机写入(基准测试)。看起来如果我注释掉 mutex lock
创建的文件大小小于实际大小,就好像有些写入丢失了(总是块大小的倍数)。但如果我保留互斥体,它总是精确的大小。
我的代码在其他地方有问题吗,实际上不需要互斥锁(@evan )或者这里需要互斥锁
void *DiskWorker(void *threadarg) {
FILE *theFile = fopen(fileToWrite, "a+");
....
for (long i = 0; i < noOfWrites; ++i) {
//pthread_mutex_lock (&mutexsum);
// For Random access
fseek ( theFile , randomArray[i] * chunkSize , SEEK_SET );
fputs ( data , theFile );
//Or for sequential access (in this case above 2 lines would not be here)
fprintf(theFile, "%s", data);
//sequential access end
fflush (theFile);
//pthread_mutex_unlock(&mutexsum);
}
.....
}
您肯定需要互斥锁,因为您要发出几个不同的文件命令。底层文件子系统不可能知道你要调用多少文件命令来完成你的整个操作。
所以你需要互斥锁。
在您的情况下,您可能会发现将互斥体 放在 循环之外可以获得更好的性能。原因是,否则,线程之间的切换可能会导致磁盘不同部分之间的过度跳跃。硬盘大约需要 10ms
来移动 read/write 磁头,这样可能会大大降低运行速度。
因此,对其进行基准测试可能是个好主意。
您正在使用 "append mode" 打开文件。根据 C11:
Opening a file with append mode ('a'
as the first character in the
mode argument) causes all subsequent writes to the file to be forced
to the then current end-of-file, regardless of intervening calls to
the fseek
function.
C 标准没有指定具体应该如何实现,但是在 POSIX 系统上,这通常使用 open
函数的 O_APPEND
标志来实现,而刷新数据是使用函数 write
。请注意,您的代码中的 fseek
调用应该没有任何效果。
我认为 POSIX 需要这个,因为它描述了如何通过 the shell:
在追加模式 (>>
) 中重定向输出
Appended output redirection shall cause the file whose name results
from the expansion of word to be opened for output on the designated
file descriptor. The file is opened as if the open() function as
defined in the System Interfaces volume of POSIX.1-2008 was called
with the O_APPEND flag. If the file does not exist, it shall be
created.
而且由于大多数程序使用FILE
接口向stdout
发送数据,这可能需要fopen
使用open
在写入数据时使用 O_APPEND
和 write
(而不是像 pwrite
那样的功能)。
因此,如果在您的系统 fopen
上使用 'a'
模式使用 O_APPEND
并且使用 write
完成刷新并且您的内核和文件系统正确实现 O_APPEND
标志,使用互斥锁应该没有效果,因为写入 do not intervene:
If the O_APPEND
flag of the file status flags is set, the file
offset shall be set to the end of the file prior to each write and no
intervening file modification operation shall occur between changing
the file offset and the write operation.
请注意,并非所有文件系统都支持此行为。检查 this 答案。
至于我对你之前问题的回答,我的建议是删除互斥锁,因为它对文件的大小应该没有影响(而且它对我的机器没有任何影响)。
就个人而言,我从未真正使用过 O_APPEND
并且会犹豫是否这样做,因为它的行为在某种程度上可能不受支持,而且它的行为在 Linux 上很奇怪(参见 "bugs" pwrite
的部分)。
我正在尝试使用多线程 (pthread) 对文件进行随机写入(基准测试)。看起来如果我注释掉 mutex lock
创建的文件大小小于实际大小,就好像有些写入丢失了(总是块大小的倍数)。但如果我保留互斥体,它总是精确的大小。
我的代码在其他地方有问题吗,实际上不需要互斥锁(@evan
void *DiskWorker(void *threadarg) {
FILE *theFile = fopen(fileToWrite, "a+");
....
for (long i = 0; i < noOfWrites; ++i) {
//pthread_mutex_lock (&mutexsum);
// For Random access
fseek ( theFile , randomArray[i] * chunkSize , SEEK_SET );
fputs ( data , theFile );
//Or for sequential access (in this case above 2 lines would not be here)
fprintf(theFile, "%s", data);
//sequential access end
fflush (theFile);
//pthread_mutex_unlock(&mutexsum);
}
.....
}
您肯定需要互斥锁,因为您要发出几个不同的文件命令。底层文件子系统不可能知道你要调用多少文件命令来完成你的整个操作。
所以你需要互斥锁。
在您的情况下,您可能会发现将互斥体 放在 循环之外可以获得更好的性能。原因是,否则,线程之间的切换可能会导致磁盘不同部分之间的过度跳跃。硬盘大约需要 10ms
来移动 read/write 磁头,这样可能会大大降低运行速度。
因此,对其进行基准测试可能是个好主意。
您正在使用 "append mode" 打开文件。根据 C11:
Opening a file with append mode (
'a'
as the first character in the mode argument) causes all subsequent writes to the file to be forced to the then current end-of-file, regardless of intervening calls to thefseek
function.
C 标准没有指定具体应该如何实现,但是在 POSIX 系统上,这通常使用 open
函数的 O_APPEND
标志来实现,而刷新数据是使用函数 write
。请注意,您的代码中的 fseek
调用应该没有任何效果。
我认为 POSIX 需要这个,因为它描述了如何通过 the shell:
在追加模式 (>>
) 中重定向输出
Appended output redirection shall cause the file whose name results from the expansion of word to be opened for output on the designated file descriptor. The file is opened as if the open() function as defined in the System Interfaces volume of POSIX.1-2008 was called with the O_APPEND flag. If the file does not exist, it shall be created.
而且由于大多数程序使用FILE
接口向stdout
发送数据,这可能需要fopen
使用open
在写入数据时使用 O_APPEND
和 write
(而不是像 pwrite
那样的功能)。
因此,如果在您的系统 fopen
上使用 'a'
模式使用 O_APPEND
并且使用 write
完成刷新并且您的内核和文件系统正确实现 O_APPEND
标志,使用互斥锁应该没有效果,因为写入 do not intervene:
If the
O_APPEND
flag of the file status flags is set, the file offset shall be set to the end of the file prior to each write and no intervening file modification operation shall occur between changing the file offset and the write operation.
请注意,并非所有文件系统都支持此行为。检查 this 答案。
至于我对你之前问题的回答,我的建议是删除互斥锁,因为它对文件的大小应该没有影响(而且它对我的机器没有任何影响)。
就个人而言,我从未真正使用过 O_APPEND
并且会犹豫是否这样做,因为它的行为在某种程度上可能不受支持,而且它的行为在 Linux 上很奇怪(参见 "bugs" pwrite
的部分)。