5

I want to find out if a pthread lock variable is locked or not. One simple approach is to use a trylock as shown below

pthread_mutex_t lockVar;
if(pthread_mutex_trylock(&lockVar) == 0)
{
    //lock was successful
    pthread_mutex_unlock(&lockVar);
}
else
{
    //someone else holds the lock
}

How do I do the same thing without obtaining a lock?

arunmoezhi
  • 3,082
  • 6
  • 35
  • 54

2 Answers2

7

When you have multiple executions happening concurrently, there is no notion of "simultaneity". Events cannot be given a global order in time, except for when explicit synchronizations happen. There is no property that's observable from within the language that can observe any kind of ordering in general.

Specifically, the question "is that mutex over there locked" is meaningless. It has no answer upon which you can act. Whatever the fictitious answer is, the state of the mutex can change right after. There is nothing you can do with an answer like "yes, it's locked" (it might become unlocked at the same time), or "no, it's unlocked" (it may get locked before you get there).

The only thing you can do with a mutex is try to lock it. You either fail, and thus know that it was locked, or you succeed and thus know that it wasn't, and now you have the lock.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Thanks for the explanation. `Whatever the fictitious answer is, the state of the mutex can change right after`. So what?. `It has no answer upon which you can act`. Why? – arunmoezhi Sep 05 '14 at 21:34
  • @arunmoezhi: The only way the answer would be meaningful is if there are invariants in your program such as the impossibility of another thread locking the mutex again once it unlocks it. And in a case like that, you could just keep the mutex locked once you get it via trylock, since you won't be blocking any other thread's forward progress by doing so. – R.. GitHub STOP HELPING ICE Sep 05 '14 at 21:39
  • I think the question "is that mutex over there locked" is meaningful in a concurrent setting which is relaxed in the sense that partial order is sufficient for correctness – arunmoezhi Sep 05 '14 at 21:40
  • In any case, the way you're doing it right now is the only possible, and only *potentially-correct*, way of doing it. But it's likely that your desire to even ask this question is misguided. – R.. GitHub STOP HELPING ICE Sep 05 '14 at 21:40
  • 1
    @arunmoezhi: If you can't accept the answer as given, I think you need to explain what you want to do with the answer in order for Kerrek or I to address whatever remaining confusion you have about his answer. – R.. GitHub STOP HELPING ICE Sep 05 '14 at 21:42
  • I think his answer is correct when you need total order as a correctness criteria. I should have mentioned in the question that I'm not looking for a total order. This is a requirement I have in a concurrent algorithm, where it is ok for the mutex value to get changed after I read it – arunmoezhi Sep 05 '14 at 21:46
  • @arunmoezhi: It's not about total order. It's about whether some property *exists*. In order to exist, something must be able to make some kind of difference. I can give you `bool is_mutex_locked(pthead_mutex_t *) { return true; }`, there there is *no* way that you could prove that that function isn't correct (without some other, intervening synchronisation). – Kerrek SB Sep 05 '14 at 21:57
  • 1
    @KerrekSB: Surely there is. If no other threads exist, the function isn't correct. There are lots of other ways you could prove it's wrong. This is actually an interesting topic, because lots of people mistakenly think you can't prove a buggy implementation of trylock is wrong, but you can. The topic came up during addition of lock elision to glibc, and again during the alignment of POSIX with the C11 memory model. :-) – R.. GitHub STOP HELPING ICE Sep 05 '14 at 22:00
  • @R..: If your program is single threaded, then you trivially have synchronization points everywhere, which I was trying to exclude in my argument. Yes, if you order the way things happen, things will happen in order, no doubt :-) – Kerrek SB Sep 05 '14 at 22:15
2

Regardless of what you want to do with the result, the way you're doing it right now is the only way. You cannot simply query whether a mutex is locked without locking it. If you want a synchronization primitive for which you can query the status without modifying it, POSIX semaphores would be a possibility. A binary semaphore can serve as a lock (although it lacks the concept of an owner, which may be a problem for you if you need recursive locking) and sem_getvalue can determine whether or not the semaphore is "locked" at a single moment in time.

As for whether the question you're asking is even meaningful, Kerrek has already told you it's usually not. Here are a few possible, minimally-useful pieces of information you could gather from negative or positive results:

  • Negative:

    • If you know the lock started out locked, and won't be locked again once it's unlocked, this tells you an operation has finished. Here, a trylock-and-unlock approach would prevent multiple threads from being able to do this, since it would break the "never locked again once it's unlocked" invariant.
    • May indicate that it's worth preparing data, without the lock held, that you could apply later via trylock/unlock held only for a brief interval once the data is prepared. But of course you have to prepare for the case where things have changed by the time you take the lock later.
  • Positive:

    • If you know that the lock will not be unlocked once it's taken until your thread performs a further action allowing the lock-holder to proceed, this gives you information that a lock-holder has arrived.
  • Maybe others...

But for the most part, "is the mutex locked?" is not a useful question.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • The thing about, say, your first point, "an operation has finished", is that you cannot *rely* solely on this technique, since you may never observe the finishing that way. Therefore, you are *already* going to have to write a separate code path to handle the general case. At that point you can most likely just drop the special case code path... – Kerrek SB Sep 05 '14 at 22:00
  • @KerrekSB: If you don't need memory to be synchronized (e.g. perhaps you just need ordering in some operations on file descriptors), just the knowledge that the operation finished might be sufficient with no additional synchronization. I agree it's usually wrong and I've been trying to convince OP of this, but I thought some examples of limited special cases where you *can* use the result might be informative to help OP realize that in most cases you *can't*. – R.. GitHub STOP HELPING ICE Sep 05 '14 at 22:02
  • I'm sorry I still don't get your point. A mutex variable starts with `unlocked` state. Then it changes to `locked`,`unlocked`,`locked`... Lets say if an observer wants to read the state of the mutex variable (not necessarily the current state). Let's say he read the value as `locked`. But by the time he/she read it the value could have changed to `unlocked`. But the value he/she read was some valid state in the past. If the value he read is NOT a value from the past or the present then I'm in trouble. But as long as it is part of the history I'm ok. – arunmoezhi Sep 05 '14 at 22:07
  • @arunmoezhi: The point is that without synchronization *there is no history*. There is no "past". "Past" implies time ordering, but there isn't one (unless you synchronize). – Kerrek SB Sep 05 '14 at 22:14
  • This give a notion of what I'm trying to ask. http://en.wikipedia.org/wiki/Linearizability#Definition_of_linearizability – arunmoezhi Sep 05 '14 at 22:17
  • @KerrekSB: The ability to read the state defines some kind of order. It might not be part of a total order on loads and stores, but it's still a type of order. For example, if multiple calls to a hypothetical "lock state query" function returned unlocked,locked,unlocked, in that order, this would potentially order them with respect to locking operations in other threads. – R.. GitHub STOP HELPING ICE Sep 05 '14 at 22:18
  • @R.. I agree with your comment. This has partial order. – arunmoezhi Sep 05 '14 at 22:22