Really?
No, he doesn't.You quit before you unlock the mutex.
Certainly not because he calls quit().So it stays locked forever.
No, it's not. It completely doesn't make any sense at all to call tryLock here.Also, a better way to lock is tryLock(someTimeOut).
Ok. May be not. So you are right.
If ~QThread() will wait for QMutex to unlock before destroy - it will stay locked forever.No, he doesn't.
I think yes because he cannot leave the loop. In fact simple form will look like:Certainly not because he calls quit().
I mean if you want to lock - better do it with tryLock (or check with isLocked before) because you can escape the thread lockout in order to write non-blocking threads.No, it's not. It completely doesn't make any sense at all to call tryLock here.
QThread object is not destroyed there so it won't wait for anything.
That's what I have written two posts ago. But it has nothing to do with quit() that he calls.I think yes because he cannot leave the loop. In fact simple form will look like:
So what in this situation do you think he should do if tryLock() fails? And please tell me how to avoid thread starvation with tryLock() as I'm sure you will agree that using tryLock() instead of lock() creates a possibility of starving the thread.I mean if you want to lock - better do it with tryLock (or check with isLocked before) because you can escape the thread lockout in order to write non-blocking threads.
Ok. I think about something like that:So what in this situation do you think he should do if tryLock() fails? And please tell me how to avoid thread starvation with tryLock() as I'm sure you will agree that using tryLock() instead of lock() creates a possibility of starving the thread.
Qt Code:
if (mutex.tryLock(5)) { // do something mutex.unlock(); return true; // action succeeds } else return false; //Just quit. No starving. We can try next timeTo copy to clipboard, switch view to plain text mode
Also in other threads where we need to call the function we can use wait call with arbitrary timing. Do you agree?
But then he won't perform the functionality he is interested in...
No. This is a good way to starve the thread.Also in other threads where we need to call the function we can use wait call with arbitrary timing. Do you agree?
If you have at least two threads and each of them spends some time in the critical section then if you use tryLock() with a timeout that is less than the time spent in the critical section then one of the threads will never succeed to lock the mutex because the other one would always be faster in accessing the lock. On the other hand if the time spent in the critical section is smaller than the lock timeout, there is no sense in using tryLock() because it will always succeed.
Another situation - if you have many threads that try to access the critical section with a try-lock semantics at the same time, most of them will fail in doing so and will have to try again in a moment. When they do, there is a good chance that those threads that managed to access the critical section decided to do that again and they managed to get into the waiting queue before the threads that failed the last time (because they had to wait the whole timeout, fail, do something and re-enter the queue). Now the fact that in normal circumstances prevents starvation of waiting threads (that is fifo semantics of the mutex) will cause threads using tryLock() to starve because when they re-enter the queue, they will be put at the end of it with a good chance of resigining before they have a chance to do their job. The worst case scenario is that a thread will resign just a cycle before it would have made it into the critical section so at the time you check the result of the operation the critical section may already be available and the value of tryLock() has become stale.
A side effect of all this is increased CPU usage caused by busy loops and context switching resulting in less time for executing the application logic and thus slowing down existing threads, increasing chances for timeouts, etc. All of this can be avoided by using a blocking call to lock.
Bottom line: in 99.9% of the cases using tryLock() instead of lock() is a bad idea.
Qt Assistant quote:
According to Assistant tryLock on non-recursive mutexes is better way than lock which can lead the thread to deadlock while tryLock not. It will pop up immediately. Also to escape race condition described in your post I suggest to use wait time based on random condition. In fact lock will lead threads in a queue block and stand still while you want them to do something useful.void QMutex::lock ()
Locks the mutex. If another thread has locked the mutex then this call will block until that thread has unlocked it.
Calling this function multiple times on the same mutex from the same thread is allowed if this mutex is a recursive mutex. If this mutex is a non-recursive mutex, this function will dead-lock when the mutex is locked recursively.
See also unlock().
bool QMutex::tryLock ()
Attempts to lock the mutex. If the lock was obtained, this function returns true. If another thread has locked the mutex, this function returns false immediately.
If the lock was obtained, the mutex must be unlocked with unlock() before another thread can successfully lock it.
Calling this function multiple times on the same mutex from the same thread is allowed if this mutex is a recursive mutex. If this mutex is a non-recursive mutex, this function will always return false when attempting to lock the mutex recursively.
Somehow I can't see the word "better" in what you quoted. And yes, tryLock() will not dead-lock, it will simply always fail. Deadlock is a logical error. If your application deadlocks, it is not caused by the fact you used lock() instead of tryLock() but rather that your logic is invalid (i.e. you used a non-recursive mutex in a resursive situation).
Seems like a "russian roulette" approach... "If we're lucky, it won't starve".Also to escape race condition described in your post I suggest to use wait time based on random condition.
That's the whole point of using thread synchronization. Threads won't be doing anything useful if you starve them. If you want to do something while waiting for the critical section then do it in another thread that won't have to wait - use a thread pool or something.In fact lock will lead threads in a queue block and stand still while you want them to do something useful.
Last edited by wysota; 8th December 2009 at 15:38.
I prefer Monte-CarloSeems like a "russian roulette" approach... "If we're lucky, it won't starve".
I thought that we are talking about processing in 2 different threads. That is the whole point. If you need to reenter the same thread then yes. You are right in all posts. But for two and more threads I do prefer to stick with tryLock approach.That's the whole point of using thread synchronization. Threads won't be doing anything useful if you starve them. If you want to do something while waiting for the critical section then do it in another thread that won't have to wait - use a thread pool or something.
P.S. It is quite interesting for me to understand more about different ways to write correct non-blocking thread-based code for myself. So, may be you will be so kind to join a discussion in different topic about that particularly. And thank you for your patience answering my potentially stupid questions![]()
Monte-Carlo only makes sense for a vast sample space, like 10000 samples at least. I doubt you're running 10000 threads at once in your application.
Do that but please don't post under my posts stating that it is better to use tryLock() instead of lock() because I will always be contesting that statement. It is plainly false and you have no arguments for backing up your claims. You failed to prove any of your points. And no matter the number of threads - tryLock() simply shouldn't be used. Ever (unless you have a very very very specific reason to do that). There is not one thing you could do with tryLock() that you couldn't do without it but there are many things that can be done without tryLock() but not with tryLock(). The only place where I see tryLock() could be useful is when dealing with a time-critical resource in a real-time operating system where you prefer to fail an operation than to extend past a designated time frame. But certainly not in a general case.But for two and more threads I do prefer to stick with tryLock approach.
Ok. Just looked into tryLock implementation in original Qt code. tryLock() is a non-blocking alternative to lock(). Also it is simpler. If you do prefer complete blocking solution then lock() is the only choice. But non-blocking implementation requires tryLock(). Agree?
Bookmarks