In php, it is possible to simultaneously access a file with locks for writing LOCK_EX (exclusive write access) and for reading LOCK_SH (general access for reading) The lock is called after opening the file through a flock

When a lock is called, the behavior depends on the type of lock. In general, it works similarly to ReaderWriterLock and in c # you need to use it for this behavior. However, ReaderWriterLock in c # works within one process (and does not relate directly to files).

Moreover, windows will interfere with simultaneous access to the file from different processes.

In c # there is FileShare, but it seems that this is just allowing another process to open the file for the same type of access (from msdn it’s not very clear what it really is)

Give an example of how to make the same blocking behavior with a common file in c # as in php or its abstract equivalent ReaderWriterLock

upd : I see an explanation is required what kind of behavior is expected; let's say there are several processes that almost simultaneously want

  1. to read
  2. to read
  3. to read
  4. write
  5. to read
  6. write

The first 3 will receive permission for simultaneous reading. The 4th waits and receives a block for recording when the first 3 release the file. The 5th will wait until the 4th releases, and the 6th will not release the 5th

So, the FileShare.ReadWrite or FileShare.Write options are not honored (I checked 2 writers and I have porridge in the output). They merely indicate what the other process can do without throwing an exception. But do not protect files from simultaneous recording.

If you put an exclusive lock without FileShare, then other processes will receive exceptions, which we want to avoid

upd2: and again no one understands what the problem is.

Problem : many processes that can read and write to a file.

Purpose : to protect the general file from concurrent access so that only one writer could write at a time. Not “deny access to others”, but provide competing access when many readers can read a lot at once, but write only one, that is, what ReaderWriterLock is for (I don’t see any fundamental difference between it and the file blocking system in php)

The option "catch exceptions and repeat after 100ms to the victorious" does not hold water. A writer who waits until the file is free may never wait, because in these 100ms a lot of readers can open the file for themselves. The correct solution is that the read / write lock is put in a queue and in php (and not only in it) it is available out of the box, but in c # I have not found how it is done.

In short, the question is: how to make a ReaderWriterLock for files that go between several processes?

  • Somewhere you got it wrong. Judging from the description of the behavior of locks in PHP, it is absolutely not similar to ReaderWriterLock - Pavel Mayorov
  • @PavelMayorov well, why. It’s quite the same thing - readers don’t interfere with each other, but if a writer comes along and gets to the protected section and declares a lock, all readers will wait. They will not fall with exceptions, but they will wait - vitidev
  • Then I don’t understand what "simultaneous acquisition of two locks" means. You can't do that with ReaderWriterLock — until someone gets a write lock, the rest have to wait. - Pavel Mayorov

2 answers 2

Understood in the chat, what I wanted from me.

Using the FileAccess / FileShare pair does not achieve the desired behavior. The required behavior in WInAPI is available through LockFileEx , use in C # can be seen here: https://stackoverflow.com/questions/1784195/using-lockfileex-in-c-sharp

  • And why not just FileShare.Read for readers and FileShare.None for writers? Explain that we also understand. - VladD
  • @VladD with FileShare.Read the writer will have to seize the moment to get into his FileShare.None. And this is really try..catch where at any moment another bunch of readers can get into, instead of becoming in a non-existent queue. - vitidev
  • @VladD active polling vs blocking or asynchronous call. Plus, in LockFileEx, the application itself for an exclusive lock can block the reader - while in the FileAccess / FileShare approach, a “fasting” situation is possible. - Pavel Mayorov
  • @PavelMayorov: Well, yes, an active poll with exponential delays, in my opinion, is quite adequate, considering that you still have to catch exceptions and try to rediscover the file (temporary network drive failure? Slow recognition by the flash drive system?) - VladD
  • @vitidev: Well, yes, race, but since we have several processes, no one in any case guarantees “fair distribution” of the right to block. We do not have RTOS. - VladD

Behavior similar to that described in PHP:

 File.Open(path, mode, FileAccess.ReadWrite, FileShare.Read) 

This command opens a file for reading and writing, and at the same time allows other processes to open the file for reading (thereby holding the write lock).

 File.Open(path, mode, FileAccess.Read, FileShare.ReadWrite) 

This command, on the contrary, opens the file for reading - and at the same time allows other processes to both file and write it.


Behavior similar to ReaderWriterLock:

 File.Open(path, mode, FileAccess.ReadWrite, FileShare.None) 

This is an exclusive file lock, with opening it in read-write mode.

 File.Open(path, mode, FileAccess.Read, FileShare.Read) 

This is a non-exclusive file lock, with opening it in read mode.


Well, there are still 14 combinations left unaddressed :)

  • And what will happen if 2 processes want to get a lock on the record? Will they write at the same time or will they be in the queue? msdn this question is not lit - vitidev
  • Depends on what you understand by “write lock”. - Pavel Mayorov
  • In the examples I have given, the operations of opening a file for writing are exclusive, since they prohibit writing for others. - Pavel Mayorov
  • I understand that there is a file and it can be opened at the same time as you like for reading. Then a writer appears who declares an exclusive lock with the goal of writing and his request becomes in a queue and when it finally reaches the file, the file is blocked. All new readers and writers queue up and wait until the writer releases the file. There is no need to check with exceptions whether the file is available for such an operation and 2 writers will work one after the other, and not at the same time. Actually the question FileShare.ReadWrite gives the same behavior? - vitidev
  • one
    Then I do not see the answer to my main question. How should the option to get an exclusive write lock be described, so that another process, who wants to get the same lock, just waits until the first process releases? In this case, of course, readers can also declare the desire to block. FileShare, as I understand it, is just allowing / disallowing other processes, but not related to the above read-write locks “many readers, but only one writer at a time” - vitidev