Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl threads not printing correctly

If there are explicit examples in another post please let me know. I am having problems with interleaved printing from my threads. I am trying to control my threads by using a shared variable across all threads. The pseudo code below highlights the pieces of my code giving me problems. I have tried everything to make the threads wait their turns to print. Right now only a few output lines are being destroyed.

#!/usr/bin/perl                                                                                                                                
use threads;
use threads::shared;

my $PRINTFLAG :shared = 1;

Run_Threads();

sub Do_stuff{

    lock($PRINTFLAG);
    cond_wait($PRINTFLAG) until $PRINTFLAG == 1;
    $PRINTFLAG = 0;
    print "$working\n";
    $PRINTFLAG =1;
}

Sub to spawn threads.

sub Run_Threads{

    my @threads;

    for (my $i = 1; $i <= 5; $i++){
        push @threads, threads->create(\&Do_stuff);
    }

    foreach (@threads){
        $_->join;
    }
}
like image 529
zev.kronenberg Avatar asked Nov 26 '25 19:11

zev.kronenberg


1 Answers

It would seem that each thread has its own handle, and thus its own output buffer. Considering that Perl file handles can't be shared using the mechanisms in threads::shared, that's not very surprising.

That means you need to flush the handle's buffer before releasing the lock. You can do that explicitly:

select->flush();       # Flush handle currently default for print.

Or you can have perl flush automatically after every print to that handle:

select->autoflush(1);  # Autoflush handle currently default for print.
$| = 1;                # Autoflush handle currently default for print.

Note: To use the ->flush and ->autoflush methods (but not for $|=1;) before Perl 5.14, you'll need to also load IO::Handle.


By the way,

my $PRINTFLAG :shared = 1;
lock($PRINTFLAG);
cond_wait($PRINTFLAG) until $PRINTFLAG == 1;
$PRINTFLAG = 0;
print "$d\n";
$PRINTFLAG =1;

can be simplified to

my $PRINTMUTEX :shared;
lock($PRINTMUTEX);
print "$d\n";
like image 112
ikegami Avatar answered Nov 29 '25 16:11

ikegami



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!