user3446683
user3446683

Reputation: 69

perl multithreading issue for autoincrement

I'm writing a multi threaded perl script and storing the output in a csv file. I'm trying to insert a field called sl.no. in the csv file for each row entered but as I'm using threads, the sl. no. overlaps in most. Below is an idea of my code snippet.

for ( my $count = 1 ; $count <= 10 ; $count++ ) {
    my $t = threads->new( \&sub1, $count );
    push( @threads, $t );
}

foreach (@threads) {
    my $num = $_->join;
}

sub sub1 {
    my $num = shift;

    my $start = '...';    #distributing data based on an internal logic
    my $end   = '...';    #distributing data based on an internal logic
    my $next;

    for ( my $x = $start ; $x <= $end ; $x++ ) {
        my $count = $x + 1;

        #part of code from which I get @data which has name and age

        my $j = 0;
        if ( $x != 0 ) {
            $count = $next;
        }
        foreach (@data) {
            #j is required here for some extra code
            flock( OUTPUT, LOCK_EX );
            print OUTPUT $count . "," . $name . "," . $age . "\n";
            flock( OUTPUT, LOCK_UN );
            $j++;
            $count++;

        }
        $next = $count;
    }

    return $num;
}

I need the count to be incremented which is the serial number for the rows that would be inserted in the csv file. Any help would be appreciated.

Upvotes: 1

Views: 71

Answers (2)

ikegami
ikegami

Reputation: 385789

You're already providing mutual exclusion using flock, so might as well take advantage of it if that's the only place $count is used.

my $counter :shared;  # Once for all threads
for (@data) {
    ...
    flock( OUTPUT, LOCK_EX );
    print OUTPUT ++$count . "," . $name . "," . $age . "\n";
    flock( OUTPUT, LOCK_UN );
 }

Or we can switch to just using Perl locks.

my $counter :shared;  # Once for all threads
for (@data) {
    ...
    {
       lock $counter;
       print OUTPUT ++$count . "," . $name . "," . $age . "\n";
    }
 }

In both cases, the lines in the output file will be numerical order.

Upvotes: 1

Alcanzar
Alcanzar

Reputation: 17155

You'll want to do something like this:

use threads;
use threads::shared;

my $counter :shared;
$counter = 1;

sub nextValue() {
  lock $counter;
  return $counter++;
}

And then just call nextValue() in your code. This will insure that only one thread at a time increments the shared counter.

Upvotes: 2

Related Questions