Re: (forks) When do I need to lock variables?

[email protected] (Elizabeth Mattijsen)
Newsgroups perl.ithreads
Message-ID <p05111b16bb963ab92d55@[192.168.56.4]>
At 08:31 +0000 9/23/03, Steve Schein wrote:
>  > In general, increment on a shared variable is not safe.  It's safe in
>>  the sense that Perl won't crash.  It's _not_ save in the sense that
>>  you might miss increments.  This is because shared variables in Perl
>>  are implemented as tied variables, i.e. with a FETCH and STORE.  An
>>  increment is this basically a FETCH, an increment and a STORE.  If
>>  second thread does a FETCH before the first one has done the STORE,
>  > you have lost 1 increment.
><<< I'm interested in this discussion because I'm sharing a hash across
>threads (threads::shared) and it is getting updated quite frequently.
>My current assumption is that for
>$hash{$index}[$array_pos] += 1;
>thread 1 could write to $hash{0}[0] at the same time thread 2 writes to
>$hash{1}[0] without any chance of missing an update.

This won't work for an entirely different reason.  You can't put a 
reference to an unshared value in a shared scalar:

use threads;
use threads::shared;
my $bar;
my $foo : shared;
$foo = \$bar;

gives:

Invalid value for shared scalar at x line 5.

So you can't have %hash : shared _and_ put an array reference as the 
value associated with a key of that hash.  However, if you would mark 
the array as shared beforehand, e.g.

$hash{$index} = &share( [] );

but this gets pretty convoluted pretty quickly.


>Is it necessary to
>lock %hash each time it is necessary to write to it?

Only when you are adding keys or removing keys.  And then only if you 
need to do something specific when you're adding a key as opposed to 
updating a key.  Internally, the threads module will also do some 
locking to ensure the consistency of the Perl structures, but you 
don't need to worry about that.


>Are these expressions handled differently?
>1) $hash{$index}[$array_pos] += 1;
>2) $hash{$index}[$array_pos]++;

Not really: they're both a tied FETCH and STORE operation internally.


>Finally, when updating such a data structure are there efficiencies in
>checking values (not committing to a write) prior to updating, eg.
>
>$new_value = 1;
>
>if ($hash{1}[1] == $new_value) {
>	print "Don't update for identical value!\n";
>}
>else
>	$hash{1}[1] = $new_value;
>}

Depends.  If chances are that they are the same, the extra if check 
will cost you a FETCH but will save you a STORE.  On the other hand, 
if chances are that they are different, then the check will cost you 
an extra FETCH on top of the FETCH and STORE.  And this of course 
compounded by the fact you're doing this 2 levels deep.


Liz
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.