David Mitchell wrote:
> I let the Perl developers do all
> the hard locking code behind the scenes, and I don't have to worry my
pretty
> little head about it.
> Now, there may be practical reasons why it isnt possible for perl to do
> this for me automatically (reasons, anyone?), but it's a nice
> ideal.
>
> Dave M.


The thing with mandatory locks per variable, is that as long as you only
want to access _that_ variable, it's ok, but if you want to make several
uses of several variables and want to do it all at once, you've got a
problem. Suppose we have:

    $a++;
    $x = $a;
    $y = $a;
    die if ($x != $y);    ## will die on a MT environment

well, if every access to the variable is mandatory, then this code would
execute the following operations:

    lock $a
    load $a
    inc
    store $a
    unlock $a
    lock $a
    lock $x
    load $a
    store $x
    unlock $a
    unlock $x
    lock $a
    lock $y
    load $a
    store $y
    unlock $a
    unlock $y
    ...

See the problem with this code? A statement using $x or $a cannot run
while $x = $a is running, because both variables are locked. That assures
$x = $a is executed without problems, but any statement modifying $a (for
example, $a++) could get to run between $x = $a and $y = $a, and so $x and
$y will hold different values. So, instead of locking the variables for
each statement, you should better lock them for the whole block of
statements.

    lock $a;
        $a++;
        $x = $a;
        $y = $a;
        die if ($x != $y);    ## won't ever die
    unlock $a;



AFAIK, Java locks the non-local variables for every statement. I think I
read this somewhere but I can't remember where. I guess this kind of
locking makes the statement

    $x = $a + $a;

run with the same value of $a for both operands. (I could be wrong, and I
think even if there was no locking, the VM could read $a only once and
use the two operands from the same reading, by copying from a local
register to other, or duplicating it on the stack...). Please correct me
if I'm wrong, but I think that is the kind of thing Java does. If anyone
can find it written somewhere, please post.


Well, IMO, this kind of locking is very weak. If instead of writing

    $x = $a + $a;

you wrote

    $x = $a;
    $x += $a;

You would loose all the locking behaviour that would guarantee that the
two $a's are the same. This goes even worse in Perl, because you know
Perl has too much special cases, and there are many more ways to do it,
and you would always have to think "Is this a statement?" or "Is the
lock working?", etc.

That's why I think, in perl,

    $x = $a + $a;

should behave as

    $x = $a;
    $x += $a;

i.e., with no locking, and no guarantee that the two reads of the non-local
variable $a will return the same thing. (I'm not saying they _always_ will
return different things, neither that they _eventually_ will return
different
things, only that it's not guaranteed that they will return the same thing!)

How can one force the sane behaviour, of returning the same thing for both
reads? In all the cases, by setting an explicit lock on $a.



The bottom line is: If you are gonna write a threaded program, you can be
lazy
or careful. If you're lazy, just let it run with no locks in it and pray so
that no race conditions occur. If you're careful, you will promptly identify
which variables are shared, and just put locks around any section of the
code
that either reads or writes to that variable (or variables).



I've read so many wrong implemented thread programs written in Java that I
almost think they shouldn't include threads in it. People read "Java is
thread-safe" and go on using it as they wouldn't ever go into this kind of
situation. But race conditions are probably the hardest type to spot,
hardest to reproduce kind of things that lead to bugs. I think the less
magic we put into locks, the more we enforce programmers to be conscient
about race conditions in multi-threading.


- Branden

Reply via email to