读取/预制系统调用的线程安全性

时间:2011-03-11 02:22:04

标签: c multithreading asynchronous thread-safety

我在多线程环境中几乎没有与read()/ pread()系统调用相关的查询

我正在使用基于freeBsd的Mac-OSX,如果这有任何帮助的话 我只在读模式下使用此文件,而不是读/写 语言是c / c ++

假设我们在磁盘上有一个文件 AAAABBBBCCCCDDDEEEE ....

和4个字母适合文件的一页

所以Page1:AAAA

2页:BBBB .....等等

现在我从具有相同文件描述符的两个不同线程启动读取系统调用 我的意图是从线程1读取第一页,从线程2读取第二页,等等。

读(FD,浅黄色,的sizeof(页));

从手册页我理解读取也会增加文件指针,所以我肯定会得到像#/ p>这样的乱码

ABCC ABBB ..等(没有特别的顺序)

要解决这个问题,我可以使用pread()

“Pread()执行相同的功能,但从speci中读取      在不修改文件指针“//从手册页

中修复文件中的位置

但我不确定使用pread是否真的会帮助我实现目标,因为即使它没有增加内部文件指针,也无法保证响应不会混乱。

我的所有数据都是页面对齐的,我想从每个线程中读取一页,如

线程1读取:AAAA 线程2读取:BBBB 线程3读取:CCCC ...没有实际的内容..

我还找到了帖子Is it safe to read() from a file as soon as write() returns?

但它没有用。

我也不确定read()是否真的会有问题,我正在考虑。我正在阅读的文件是一个二进制文件,因此我很难快速手动阅读和验证..

任何帮助将不胜感激

3 个答案:

答案 0 :(得分:9)

readwrite更改基础打开文件的位置。它们是“线程安全的”,因为如果多个线程使用它们同时在同一个打开的文件上执行IO,那么您的程序将不会有未定义的行为(崩溃或更糟),但操作的顺序和原子性可能会有所不同,具体取决于文件类型和实现。

另一方面,preadpwrite不会更改打开文件中的位置。它们被添加到POSIX中以达到您想要的目的:在多个线程或进程的同一个打开文件上执行IO操作,而不会使操作干扰彼此的位置。如果您将preadpwrite(或多次调用pwrite)与文件的重叠部分混合,您仍可能会遇到一些排序问题,但只要您避免这样做,他们对你想做的事情非常安全。

答案 1 :(得分:1)

fcntl个顾问锁是该文件的范围上的锁。您可能会发现这对于序列化对同一区域的读取和写入非常有用,同时允许在不同的区域上进行并发。

int rc;
struct flock f;
f.l_type = F_RDLCK;  /* or F_WRLCK */
f.l_whence = SEEK_SET;
f.l_start = n;
f.l_len = 1;
while ((rc = fcntl(fd, F_SETLKW, &f)) == -1 && errno = EINTR)
    ;
if (rc == -1)
    perror("fcntl(F_SETLKW)");
else {
    /* do stuff */
    f.l_type = F_UNLCK;
    fcntl(fd, F_SETLK, &f);
}

一次允许多个读取器锁定,而单个写入器锁定阻止所有其他锁定。

警告all file locking mechanisms are subtly broken on some configurations on all platforms

答案 2 :(得分:-1)

在两个线程之间共享互斥锁,在线程读取之前启用锁定,并在正确读取完成后解锁锁定。请参阅pthread_mutex_createpthread_mutex_lockpthread_mutex_unlock