I need to implement a locking scheme so that multiple processes can share a set of resources, while a "special" process can obtain exclusive access to that set of resources.

These are batch processes: at the beginning of each transaction I propose to acquire the appropriate lock, and release it at the end, ad infinitum.

flock has the semantics I need (LOCK_SH, LOCK_EX, LOCK_UN). I experimented with it using Perl Flock.pm and a dummy file whose only purpose is to be flock'ed against. I was a little surprised at how slow it was, and it wasn't evident from 'top' where the time was being spent. (It wasn't CPU-bound, even though the loop being executed consisted of nothing but LOCK_SH and LOCK_UN.) I don't want to be guilty of premature optimization, but I wanted to know whether flock is the standard method for managing shared and exclusive access to a shared resource in *nix, even when the shared resource is not an actual file, or whether there was another facility I'm unaware of.

UPDATE: @msw correctly guessed that I'd (inadvertently) locked on an NFS file instead of a local one. Using a local file completely cleared up the performance hit I was seeing. I'm leaving the question open to learn more about whether "file locking" is really the best way to go for this class of problem.

  • 1
    Is this file accessed across the net, for example, NFS or SMB/CIFS? There are a number of processes that have to coordinate flocks across those protocols and it will, of necessity, be slower than a local file. – msw Dec 18 '14 at 23:20
  • You nailed it! Yes, the file was on an NFS mount, rather than the local file system. Using a local file, it flies. Thanks. – Chap Dec 18 '14 at 23:34

Unix has a plethora of locking systems. The one you found is called BSD file locking, but there are other file locking methods. On top of that, you also have semaphores, mutexes and more.

As to your direct question, yes, it is a perfectly fine way to go. Don't worry about the time it takes. Locking is a high-overhead activity, by its very nature. This is why so much effort goes into designing lock-free mechanisms.

The only thing that bugs me about your plan is the dummy file you have to create. There may be a simpler way that achieves your desired end: mkdir(2). The call is atomic, and you get an error when the directory already exists. By contrast, open(2) is only atomic with O_EXCL, which isn't available everywhere. When available, it may not work as expected, either because you are using NFSv2 or because you haven't enabled the NFS file locking daemon.

Once nice thing about the mkdir approach is that you can do it in shell scripts, via mkdir(1). I see that you're using Perl instead, but in that case, it's a built-in function, rather than an outside module.

Another nice thing is that it will work over NFS without any special help. You can't create a directory twice.

The only problem with the mkdir() approach is that there's no way to make it wait for an existing directory to disappear. That is, it is not a blocking lock operation. I suggest that you wrap it with a timer, so that the processes contending for the lock spend most of their time asleep. I suggest that you make each process wait a random windowed period of time. For instance, between 100 and 200 ms, via usleep(3). This would create a form of spinlock.

  • @msw pointed me to the solution to the performance problem (see above - I was inadvertently using an NFS-mounted file!). The eventual solution will be coded in C, so Perl and shell won't apply. I'm not sure I fully understand your preference for mkdir, since it doesn't naturally provide queue-until-available behavior for an EXCL lock, and requires spinning. Can you elaborate on the drawbacks to flock? – Chap Dec 18 '14 at 23:52
  • @Chap: I made that suggestion because a) you mentioned Perl; and b) you're posting this on Unix.SE and not Stack Overflow. Given all that, you should probably be using a semaphore or mutex, and not any of these file-based alternatives. – Warren Young Dec 19 '14 at 0:25
  • I'm definitely looking for a Linux C solution. But having looked at this doc, mutexes appear to be used for coordinating between threads, rather than processes. – Chap Dec 19 '14 at 0:46
  • There are more flavors of mutex than just pthread mutexes. This one, for a start. Myself, I'd actually reach for a POSIX semaphore instead. But keep in mind, this is not a classroom or a discussion forum. This is a site where you ask a well-focused question and get one (or hopefully more) well-focused answers. – Warren Young Dec 19 '14 at 0:56
  • To support @WarrenYoung's point, using files or directories as poor man's semaphores dates back to when semaphores didn't (portably) exist. If I found myself needing a mutex on the local machine, I'd probably use a POSIX semaphore because that's they were invented for. – msw Dec 19 '14 at 4:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.