user210757
user210757

Reputation: 7376

How to run concurrent threads in perl?

The following does not appear to run in concurrent threads as I expected, but rather each process blocks until it is complete:

my @arr = (1,2,3,4);
foreach (@arr) {
   threads->new(\&doSomething, $_)->join;
}

sub doSomething {
    my $thread = shift;
    print "thread $thread\n";
    sleep(5);
}

In other words, it appears to be executing the same as the non-threaded version would:

my @arr = (1,2,3,4);
foreach (@arr) {
   doSomething($_);
}

I am running ActivePerl v5.10.1 mswin32-x86-multi-thread

How to I run concurrent threads in perl?

Upvotes: 9

Views: 17667

Answers (6)

user3256711
user3256711

Reputation: 1

my @arr = (1,2,3,4);
my @threads;
foreach (@arr) {
   push @threads, threads->new(\&doSomething, $_);
}
foreach (@threads) {
   $_->join();
}

The above code is working in a small scale. But if you have tens of threads or more, your OS starts to stall.

Upvotes: 0

patpicos
patpicos

Reputation: 31

If you do not care of the output generated from the thread, you can use ->detach() on the thread.

my @arr = (1,2,3,4); my @threads; foreach (@arr) {
my $t = threads->new(\&doSomething, $_); $t->detach(); }

after a thread completes, it is reclaimed and you don't need to call join() on it.

this model is good to create worker bees which you dont need to report back to you.

Upvotes: 3

Hynek -Pichi- Vychodil
Hynek -Pichi- Vychodil

Reputation: 26121

You have to call join after spawning all threads:

perl -mthreads -le'$_->join for map threads->new(sub{print"Thread $_";sleep(2)}),1..4'

Upvotes: 1

Daenyth
Daenyth

Reputation: 37431

See perldoc threads.

The problem is that calling join() on a thread waits for it to finish. You want to spawn threads and then join after, not spawn/join as one operation.

A further look at perldoc threads says:

threads->list()

threads->list(threads::all)

threads->list(threads::running)

threads->list(threads::joinable)

With no arguments (or using threads::all ) and in a list context, returns a list of all non-joined, non-detached threads objects. In a scalar context, returns a count of the same.

With a true argument (using threads::running), returns a list of all non-joined, non-detached threads objects that are still running.

With a false argument (using threads::joinable ), returns a list of all non-joined, non-detached threads objects that have finished running (i.e., for which ->join() will not block).

You can use this to loop and list threads, joining when possible, until all threads are complete (and you'll probably want an upper limit to wait time where you will kill them and abort)

Upvotes: 13

Steve Schnepp
Steve Schnepp

Reputation: 4680

you have to join them afterwards, not while creating them:

my @arr = (1,2,3,4);
my @threads;
foreach (@arr) {
   push @threads, threads->new(\&doSomething, $_);
}
foreach (@threads) {
   $_->join();
}

Upvotes: 13

join (not only in Perl) causes calling thread to wait for another thread finish. So your example spawns thread, waits for it to finish, and then spawns another thread, so you get impression that there are no threads spawned at all.

Upvotes: 3

Related Questions