ilanv has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm having a problem using the detach method in threads. I'm using ActiveState PERL 5.8.6 build 811 on a windows XP platform. Running an example out of the threads tutorial, I always get an error: use threads; $thr = threads->new(\&sub1); $thr->detach; sub sub1 { $a = 0; while (1) { $a++; print"\$a is $a\n"; sleep 1; } } A thread exited while 2 threads were running.

Replies are listed 'Best First'.
Re: Thread detach
by BrowserUk (Patriarch) on Jan 24, 2005 at 22:52 UTC

    After you set you thread running, your main thread does nothing and just runs of the end of the code. When it does so, the other thread you started is still running (in fact it will never end as it is an elndless loop) and so you get the warning.

    when you start a second thread you need to arrange for you main thread to not terminate until your second thread has finished. The normal way to do this is to use join--which precludes using detach.

    ps. Please wrap your code in code tags (see the bottom of the screen when you are posting for details).


    Examine what is said, not who speaks.
    Silence betokens consent.
    Love the truth but pardon error.
      Thank you very much. Adding a sleep at the end of my code solved the problem. The actual problem I'm trying to solve is running multiple threads on a system with 4 processors. I don't want the actual number of running threads to be larger then the processors. Each thread is a calculation and it is not possible to predict how long it will take. My model code is:
      use threads; use Thread::Semaphore; my $semaphore = Thread::Semaphore->new(4); # max number of proccesors + to use for $i (1..10) { my $thr = threads->new(\&sub1, $i); $thr->detach(); } sleep 20; sub sub1 { $semaphore->down(1); $tn = shift; print "thread $tn is working\n"; $s = int(rand 4) +1; # a long calculation sleep $s; $semaphore->up(1); }
      Can you suggest a more inteligent way to prevent the main thread from finishing. Thanks in advance.
        Can you suggest a more inteligent way to prevent the main thread from finishing.

        If all you need to do in your main thread is wait until all your other threads have finished, then don't detach them and use join in the main thread.

        #! perl -slw use strict; use threads; sub slowProcess { my( $count ) = @_; while( --$count and sleep 1 ) { print threads->self->tid(), " : $count"; } } my @threads = map{ threads->create( \&slowProcess, 1+int rand 10 ) } 1 .. 10; $_->join for @threads;

        There is a caveat with this in that if the first thread you created is the last thread to finish, then the resources used by the other 9 thread will not be freed until the first thread completes, because the code will make no attempt to join the other 9 until the first join returns. In this case, that will probably make no difference to you.


        Examine what is said, not who speaks.
        Silence betokens consent.
        Love the truth but pardon error.
Re: Thread detach
by BUU (Prior) on Jan 25, 2005 at 02:42 UTC
    Note that this shouldn't be an error, it is merely a warning that the main thread exited already. It should not affect any part of your code.
Re: Thread detach
by zentara (Cardinal) on Jan 25, 2005 at 18:47 UTC
    Since you seem to be learning threads....I'll "pound in" the basic lesson, which seems to elude most thread programmers, until they "learn by experience".

    In addition to the comment,by BrowserUk,about your "endless loop" in a thread, a thread will NOT return until it gets to the end of it's code block. It is mentioned in the docs for threads, but it isn't emphasized enough, and most programmers don't "absorb it's meaning" until they run into the warnings.

    So whether you detach, or wait to join, that warning will be there when you exit the program. You've noticed that BrowserUk's example uses a "countdown", which assures that the thread code finishes.

    You must have a mechanism, thru code design(like countdown or alarm), or some signal sent thru shared variables, to tell the thread to go to the end of it's code block, when finished. Even "sleeping threads" need to have this done, or you will get warnings.

    You may even have to catch SIG{INT}, in case you hit control-c, to shutdown the threads before exiting. Like:

    $SIG{INT} = sub{ foreach(@threads){$thread_exit{$_} = 1;} };
    or do whatever to send all running threads to the end of their code block.

    So, repeat 100 times, "a thread must reach the end of it's code block, or there will be warnings (but maybe no harm done).


    I'm not really a human, but I play one on earth. flash japh