I have a worker thread which reads data repeatedly from an MVar and performs some useful work on that. After a while, the rest of the program forgets about that worker thread, which means that it will wait on an empty MVar and become very lonely. My question is:
Will the MVar be garbage collected if threads no longer write to it, for instance because they all wait for it? Will garbage collection kill the waiting threads? If neither, can I somehow indicate to the compiler that the MVar should be garbage collected and the thread be killed?
EDIT: I should probably clarify the purpose of my question. I don't desire general protection against deadlocks; instead, what I would like to do is to tie the life of the worker thread to life of a value (as in: dead values are claimed by garbage collection). In other words, the worker thread is a resource that I would like to free not by hand, but when a certain value (the MVar or a derivative) is garbage collected.
Here an example program that demonstrates what I have in mind
import Control.Concurrent import Control.Concurrent.MVar main = do something -- the thread forked in something can be killed here -- because the MVar used for communication is no longer in scope etc something = do v <- newEmptyMVar forkIO $ forever $ work =<< takeMVar v putMVar v "Haskell" putMVar v "42"
In other words, I want the thread to be killed when I can no longer communicate with it, i.e. when the MVar used for communication is no longer in scope. How to do that?
No thread (or the things it refers to) will be garbage-collected while it is still running.
run() will finish its execution, your current thread will sleep, and your while will continue its loop and do it over and over. The GC can hit at any point and, as others have stated, running threads (threads that were started with start() ) will only be GCed if they have finished their execution.
Typically Haskell threads are an order of magnitude or two more efficient (in terms of both time and space) than operating system threads. The downside of having lightweight threads is that only one can run at a time, so if one thread blocks in a foreign call, for example, the other threads cannot continue.
It will just work: when the MVar
is only reachable by the thread that is blocked on it, then the thread is sent the BlockedIndefinitelyOnMVar
exception, which will normally cause it to die silently (the default exception handler for a thread ignores this exception).
BTW, for doing some cleanup when the thread dies, you'll want to use forkFinally
(which I just added to Control.Concurrent
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With