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

Reply via email to