PDA

View Full Version : regarding multithreading



mohanakrishnan
8th December 2009, 10:44
hi
i need to use multithreading,in my code.Here i have a function which will be called by different process.so i need it.Can any one help me with sample codes ,which shows
how to use thread with mutex?? i am trying ,but it showed errors.,probably i dont know
how to implement!!!.
thanks in advance
:):confused:

wysota
8th December 2009, 10:46
Explain what you mean by "use thread with mutex".

mohanakrishnan
8th December 2009, 12:05
hi wysota,

hi it means,normally if a function take longer time,we use threading to avoid problems,
but in my case i did it, as there are many process at the same time access the function,
we need to lock the function,so one thread can only access...

i have tried with threading ,but when many thread calls that function ,the application
hangs


mutex.lock();
while(status == 1)
{
thisthread->setPriority(QThread::LowestPriority);
thisthread->start();
}
thisthread->quit();
mutex.unlock();


This is what i have done...i will change the status=0 in a timer within some seconds(2 sec)
but due to the while loop ,the app gets hanged.and it does not allow the timer to timeout
to change the status=0
So that i am trying to use threading ,and as many process will call this while loop ,so i need a mutex to lock...
pls help me...
thanks :)

wysota
8th December 2009, 13:56
The while loop is likely to run infinitely. Mutexes or threads have nothing to do with it. The design of all this seems flawed. What do you expect to obtain with the status variable and this while loop?

Tanuki-no Torigava
8th December 2009, 14:13
hi wysota,

hi it means,normally if a function take longer time,we use threading to avoid problems,
but in my case i did it, as there are many process at the same time access the function,
we need to lock the function,so one thread can only access...

i have tried with threading ,but when many thread calls that function ,the application
hangs


mutex.lock();
while(status == 1)
{
thisthread->setPriority(QThread::LowestPriority);
thisthread->start();
}
thisthread->quit();
mutex.unlock();


This is what i have done...i will change the status=0 in a timer within some seconds(2 sec)
but due to the while loop ,the app gets hanged.and it does not allow the timer to timeout
to change the status=0
So that i am trying to use threading ,and as many process will call this while loop ,so i need a mutex to lock...
pls help me...
thanks :)

It is obvious. You quit before you unlock the mutex. So it stays locked forever. Also, a better way to lock is tryLock(someTimeOut).

wysota
8th December 2009, 14:17
It is obvious.
Really?

You quit before you unlock the mutex.
No, he doesn't.

So it stays locked forever.
Certainly not because he calls quit().

Also, a better way to lock is tryLock(someTimeOut).
No, it's not. It completely doesn't make any sense at all to call tryLock here.

Tanuki-no Torigava
8th December 2009, 14:26
Really?
Ok. May be not. So you are right.


No, he doesn't.
If ~QThread() will wait for QMutex to unlock before destroy - it will stay locked forever.


Certainly not because he calls quit().
I think yes because he cannot leave the loop. In fact simple form will look like:


while (1)
{
...
}



No, it's not. It completely doesn't make any sense at all to call tryLock here.

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.

wysota
8th December 2009, 14:35
If ~QThread() will wait for QMutex to unlock before destroy - it will stay locked forever.
QThread object is not destroyed there so it won't wait for anything.



I think yes because he cannot leave the loop. In fact simple form will look like:


while (1)
{
...
}

That's what I have written two posts ago. But it has nothing to do with quit() that he calls.



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.
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.

Tanuki-no Torigava
8th December 2009, 14:44
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.


Ok. I think about something like that:



if (mutex.tryLock(5))
{
// do something
mutex.unlock();
return true; // action succeeds
}
else
return false; //Just quit. No starving. We can try next time



Also in other threads where we need to call the function we can use wait call with arbitrary timing. Do you agree?

wysota
8th December 2009, 15:06
Ok. I think about something like that:



if (mutex.tryLock(5))
{
// do something
mutex.unlock();
return true; // action succeeds
}
else
return false; //Just quit. No starving. We can try next time


But then he won't perform the functionality he is interested in...


Also in other threads where we need to call the function we can use wait call with arbitrary timing. Do you agree?
No. This is a good way to starve the thread.

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.

Tanuki-no Torigava
8th December 2009, 15:24
Qt Assistant quote:


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.


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.

wysota
8th December 2009, 15:33
According to Assistant tryLock on non-recursive mutexes is better way than lock which can lead the thread to deadlock while tryLock not.
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).


Also to escape race condition described in your post I suggest to use wait time based on random condition.
Seems like a "russian roulette" approach... "If we're lucky, it won't starve".


In fact lock will lead threads in a queue block and stand still while you want them to do something useful.
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.

Tanuki-no Torigava
8th December 2009, 15:46
Seems like a "russian roulette" approach... "If we're lucky, it won't starve".


I prefer Monte-Carlo ;)



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.


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.

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 :)

wysota
8th December 2009, 16:02
I prefer Monte-Carlo ;)
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.


But for two and more threads I do prefer to stick with tryLock approach.
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.

Tanuki-no Torigava
8th December 2009, 16:31
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?

wysota
8th December 2009, 17:05
But non-blocking implementation requires tryLock(). Agree?

No. Read about lock-free data structures.

mohanakrishnan
9th December 2009, 04:45
hi wysota/all
thanks for ur valuable info.i ll try and come back...

mohanakrishnan
9th December 2009, 07:06
hi wysota/all
thanks for ur valuable info.i ll try and come back...


No. Read about lock-free data structures.


The while loop is likely to run infinitely. Mutexes or threads have nothing to do with it. The design of all this seems flawed. What do you expect to obtain with the status variable and this while loop?

hi wysota,

i m using the while loop to make the application to wait for some time..say about 1 or 2
secs., this worked well in csharp...ok..pls see below is my exact situation

I am writing an application which receives data from the serial port.device.
The application will receive request protocol frequently.
When the app receives a request protocol ,then it should immediately send the
acknowledgment protocol to the particular serial device,then this device will send a status
success protocol.After this status success protocol only,the app can send the acknowledgment to the next received protocol,and then receive the status success protocol and so on.,

My problem is ,how to make the app to wait for some time say about 1 r 2 sec.,
within the time it will process the request.
meanwhile there may be many requests coming to the application ,so all those requests
should be waited in queue and processed without problem.

thanks...

wysota
9th December 2009, 07:52
My problem is ,how to make the app to wait for some time say about 1 r 2 sec.,
within the time it will process the request.

Read this article, there is an example there how to halt flow of code without the need for threads and blocking the application: Keeping the GUI Responsive

mohanakrishnan
9th December 2009, 08:21
Read this article, there is an example there how to halt flow of code without the need for threads and blocking the application: Keeping the GUI Responsive

hi wyota,
i ll try it now and revert back ..
thanks,,:)