Subroutine lock doesn't work for me. Please help

P

poohc1234

Hi,
I have copied the code from perlthrtut.html with the following:
use Thread qw(yield);
new Thread \&thread_sub, 1;
new Thread \&thread_sub, 2;
new Thread \&thread_sub, 3;
new Thread \&thread_sub, 4;
sub sync_sub :locked {
my $CallingThread = shift @_;
print "In sync_sub for thread $CallingThread\n";
sleep 3;
print "Leaving sync_sub for thread $CallingThread\n";
}
sub thread_sub {
my $ThreadID = shift @_;
print "Thread $ThreadID calling sync_sub\n";
sync_sub($ThreadID);
print "$ThreadID is done with sync_sub\n";
}

But it doesn't work. The result I get was:
Thread 1 calling sync_sub
In sync_sub for thread 1
Thread 2 calling sync_sub
In sync_sub for thread 2
A thread exited while 6 threads were running.
Thread 3 calling sync_sub
In sync_sub for thread 3
Thread 4 calling sync_sub
In sync_sub for thread 4

So I changed the code to be called with join:
for (0..4)
{
$Child[$_] = threads->new(\&thread_sub, $_);
}
for (0..4)
{
$Child[$_]->join;
}
and this still doesn't work because all the threads enters the
subroutine at the same time. I know this because the code exited after
3 seconds, instead of 5 clients * 3 seconds. Though I don't understand
why 2 threads that were still executing with the code exits.

This is the result:
Thread 0 calling sync_sub
In sync_sub for thread 0
Thread 1 calling sync_sub
In sync_sub for thread 1
Thread 2 calling sync_sub
In sync_sub for thread 2
Thread 3 calling sync_sub
In sync_sub for thread 3
Thread 4 calling sync_sub
In sync_sub for thread 4
Leaving sync_sub for thread 0
Leaving sync_sub for thread 1
Leaving sync_sub for thread 2
Leaving sync_sub for thread 3
Leaving sync_sub for thread 4
A thread exited while 2 threads were running.

Very confused.
Thanks,
jiac
 
K

Kevin Sproule

jiac,

Useing a shared "lock" variable seems to work for me.

Try this:

#!/perl/bin/perl.exe

use threads;
use Thread qw(yield);
my $lock : shared;
new Thread \&thread_sub, 1;
new Thread \&thread_sub, 2;
new Thread \&thread_sub, 3;
new Thread \&thread_sub, 4;

# Loop through all the threads
foreach $thr (threads->list) {
# Don't join the main thread or ourselves
if ($thr->tid && !threads::equal($thr, threads->self)) {
$thr->join;
}
}
print "Done!\n";

sub sync_sub :locked {
my $CallingThread = shift @_;
lock($lock);
print "In sync_sub for thread $CallingThread\n";
sleep 3;
print "Leaving sync_sub for thread $CallingThread\n";
}

sub thread_sub {
my $ThreadID = shift @_;
print "Thread $ThreadID calling sync_sub\n";
sync_sub($ThreadID);
print "$ThreadID is done with sync_sub\n";
}

C:\pl>ptest.pl
Thread 1 calling sync_sub
In sync_sub for thread 1
Thread 2 calling sync_sub
Thread 3 calling sync_sub
Thread 4 calling sync_sub
Leaving sync_sub for thread 1
In sync_sub for thread 2
1 is done with sync_sub
Leaving sync_sub for thread 2
2 is done with sync_sub
In sync_sub for thread 3
Leaving sync_sub for thread 3
3 is done with sync_sub
In sync_sub for thread 4
Leaving sync_sub for thread 4
4 is done with sync_sub
Done!
A thread exited while 2 threads were running.


Kevin Sproule

Hi,
I have copied the code from perlthrtut.html with the following:
use Thread qw(yield);
new Thread \&thread_sub, 1;
new Thread \&thread_sub, 2;
new Thread \&thread_sub, 3;
new Thread \&thread_sub, 4;
sub sync_sub :locked {
my $CallingThread = shift @_;
print "In sync_sub for thread $CallingThread\n";
sleep 3;
print "Leaving sync_sub for thread $CallingThread\n";
}
sub thread_sub {
my $ThreadID = shift @_;
print "Thread $ThreadID calling sync_sub\n";
sync_sub($ThreadID);
print "$ThreadID is done with sync_sub\n";
}

But it doesn't work. The result I get was:
Thread 1 calling sync_sub
In sync_sub for thread 1
Thread 2 calling sync_sub
In sync_sub for thread 2
A thread exited while 6 threads were running.
Thread 3 calling sync_sub
In sync_sub for thread 3
Thread 4 calling sync_sub
In sync_sub for thread 4

So I changed the code to be called with join:
for (0..4)
{
$Child[$_] = threads->new(\&thread_sub, $_);
}
for (0..4)
{
$Child[$_]->join;
}
and this still doesn't work because all the threads enters the
subroutine at the same time. I know this because the code exited after
3 seconds, instead of 5 clients * 3 seconds. Though I don't understand
why 2 threads that were still executing with the code exits.

This is the result:
Thread 0 calling sync_sub
In sync_sub for thread 0
Thread 1 calling sync_sub
In sync_sub for thread 1
Thread 2 calling sync_sub
In sync_sub for thread 2
Thread 3 calling sync_sub
In sync_sub for thread 3
Thread 4 calling sync_sub
In sync_sub for thread 4
Leaving sync_sub for thread 0
Leaving sync_sub for thread 1
Leaving sync_sub for thread 2
Leaving sync_sub for thread 3
Leaving sync_sub for thread 4
A thread exited while 2 threads were running.

Very confused.
Thanks,
jiac
 
P

poohc1234

Hi Kevin Sproule,
Thanks for replying, and yes, adding the variable does help. Can I ask
you a few more questions or whoever:

1. Why the need to add the $lock variable since doesn't the subroutine
already have a lock attribute? (and since section on subroutine lock
didn't mention it.)

2. The output is " A thread exited while 2 threads were running.".
What other 2 threads are there?

3. I didn't understand your comment about "Don't join the main thread
or ourselves ". I understand the main thread part, but aren't we
suppose to join ourselves once the exeuction is done?

Thank you. I am still learning about threads.
jiac.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Help me 4
I dont get this. Please help me!! 2
Code help please 4
HELP PLEASE 4
BATCH FILES...PLEASE HELP 6
Please help 2
Please critique my code for fun learning project. 5
Help please 8

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top