0

I am writing a program, which has one write thread, and a few read threads, that write/read to a file on disk. I wish that no write / read will happen at the same time. I found many examples which uses pthread mutex lock to protect memory array during write / read, such as declaring the protected memory array volatile.

volatile int array[NUMBER];
pthread_mutex_t locks[NUMBER];

pthread_mutex_lock(&locks[index]);
array[acct] -= SOME_NUMBER;
pthread_mutex_unlock(&locks[index]);

But I cannot find examples with using pthreads to protect files on disk.

volatile FILE* array[NUMBER]; ??

Can someone point me to the right direction? I wish write / read threads will not access the files on disk simultaneously.

Edit: I read more, and according to this post, it seems that multithreading does not work with disk IO.

Community
  • 1
  • 1
Pippi
  • 2,451
  • 8
  • 39
  • 59
  • 3
    The `volatile` part is not related to the not-accessing-simultaneously. – user253751 May 04 '16 at 05:08
  • 1
    As already debated endlessly on SO, volatile does not make reads/writes atomic and cannot be used for re-entrancy purposes. However, it is good practice to declare all variables shared with a callback as volatile, to prevent incorrect code optimization by bad compilers that don't realize that code inside a callback can be executed at any time. In some cases volatile can also act as a memory barrier. – Lundin May 04 '16 at 06:51

2 Answers2

5

According to the description, your problem is about protecting the files on the disk, not the stream descriptors(FILE*) that represents the files. You can try to use pthread's rwlock to synchronize concurrent access between multiple threads:

FILE *fp = fopen(...);
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

// read thread:
char buf[BUFLEN];
pthread_rwlock_rdlock(&rwlock);
fread(buf, sizeof buf, 1, fp);
pthread_rwlock_unlock(&rwlock);

// write thread:
pthread_rwlock_wrlock(&rwlock);
fwrite(buf, sizeof buf, 1, fp);
pthread_rwlock_unlock(&rwlock);

Note that this protect the file from accessed by multiple threads in the same process, this does not protect it from accessing by multiple processes on the system.

fluter
  • 13,238
  • 8
  • 62
  • 100
  • Thank you! I read more online resources, and it seems that multithreading does not work with disk IO. – Pippi May 04 '16 at 05:26
  • @Pippi You need to consider the fact that files are resources that can be seen by everyone on the system, not only your process. So it will work under the assumption that your processes is the only users of that file. – fluter May 04 '16 at 05:28
  • I agree. Thank you for this suggestion! – Pippi May 04 '16 at 05:30
2

It depends on what you mean by "will not access the files on disk simultaneously". Since you talk about pthreads, it means you're on a POSIX system. POSIX already has certain guarantees about file access by multiple processes and threads.

If you use the raw system calls read and write you're for example guaranteed that writes will be atomic. This means that if a read and write happen simultaneously (meaning: you don't know which starts first), the read will either see the entire change to the file that the write did or none of it (there might be some exceptions here on errors). Of course there are problems with reading and writing the same file descriptor by multiple threads since read/write updates the offset where the next read/write will happen. So doing an lseek and then write is unsafe if some other thread can touch the file descriptor between the seek and the write. But for that you have the system calls pread and pwrite that guarantee that the seek+read/write will be atomic.

So by just going on this part of your problem description:

one write thread, and a few read threads, that write/read to a file on disk. I wish that no write / read will happen at the same time.

this is already guaranteed by the operating system. The problem I think is that "at the same time" is a very vague requirement because almost nothing that accesses a shared resource (like a file or even memory) happens at the same time. When thinking about threads or just about any concurrency you need to frame the problem in terms of what needs to happen before/after some other thing.

Art
  • 19,807
  • 1
  • 34
  • 60
  • Could you post the specification where `read()` and `write()` are guaranteed to be atomic? – EOF May 04 '16 at 15:34
  • @EOF http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_07 – Art May 04 '16 at 17:20