#! perl -slw
use strict;
use threads;
use threads::shared;
use List::Util qw[ shuffle ];
use Time::HiRes qw[ time ];
our $N //= 1e3;
our $W //= 20;
our $L //= 1;
my %counts :shared;
sub worker {
my @order = shuffle 1 .. 20;
for( 1 .. $N ) {
$L and lock %counts;
++$counts{ $_ } for @order;
}
}
my $start = time;
$_->join for map threads->new( \&worker ), 1 .. $W;
my $end = time;
for( sort{ $a <=> $b } keys %counts ) {
printf "%2u : %u\n", $_, $counts{ $_ };
}
printf "Took %.6f seconds\n", $end - $start;
each of the counts should end up as $N * $W, which they do with locking enabled: C:\test>junk2 -N=1000 -W=32 -L=1
1 : 32000
2 : 32000
3 : 32000
4 : 32000
5 : 32000
6 : 32000
7 : 32000
8 : 32000
9 : 32000
10 : 32000
11 : 32000
12 : 32000
13 : 32000
14 : 32000
15 : 32000
16 : 32000
17 : 32000
18 : 32000
19 : 32000
20 : 32000
Took 2.674634 seconds
But turn off the locking, and whilst the iThreads architecture will prevent internal corruption, thus no crashes, the results are silently corrupted: C:\test>junk2 -N=1000 -W=32 -L=0
1 : 25459
2 : 25272
3 : 25198
4 : 25176
5 : 25543
6 : 25338
7 : 25168
8 : 25261
9 : 25080
10 : 24649
11 : 24985
12 : 25527
13 : 25499
14 : 25351
15 : 25293
16 : 25337
17 : 25380
18 : 25224
19 : 25403
20 : 25123
Took 16.446213 seconds
And, it took 8 times longer to produce the incorrect output.
Locking is the programmer's responsibility, and the programmer's choice; but unless you're sure that you can get away without it, it's best to err on the side of caution.
Whilst your code, as is, doesn't require it; it's best not to get into the habit of omitting it, until you are very confident that you know when you can do so safely.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
p |