Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

Inconsistent results with keys on thread shared hashes

by izomiac (Initiate)
on Aug 03, 2022 at 04:22 UTC ( #11145911=perlquestion: print w/replies, xml ) Need Help??

izomiac has asked for the wisdom of the Perl Monks concerning the following question:

I've been stumped with a bug in my code for days, until I traced it down to a fairly simple subroutine that gave inconsistent results when two or more threads were running. Here's an isolated version of the problem:
#!/usr/bin/perl use strict; use warnings; $|=1; use threads; use threads::shared; my %testOne :shared = (A => 1, B => 2, C => 3, D => 4, E => 5); my %testTwo = (A => 1, B => 2, C => 3, D => 4, E => 5); my $inc :shared = 1; do { threads->create(sub { while (1){ my $i = join('', sort keys %testOne); my $j = join('', sort keys %testTwo); print "$inc-1\t$i\n" if ($i ne 'ABCDE'); print "$inc-2\t\t$j\n" if ($j ne 'ABCDE'); } }); } while (sleep 5 && $inc++ && $inc < 100);
I'm running this with Strawberry Perl on Windows, and my application uses threads so the Tk GUI doesn't freeze. I want to be able to use a lot of worker threads for a CPU-bound genetic sorting algorithm. Is this a bug in perl, or have I misunderstood something?

Replies are listed 'Best First'.
Re: Inconsistent results with keys on thread shared hashes
by ikegami (Patriarch) on Aug 03, 2022 at 06:11 UTC


    for my $t (1..2) { threads->create(sub { while (1) { my $s = join '', sort keys %testOne; print "$t\t$s\n" if $s ne 'ABCDE'; } }); } sleep;

    You are both reading and modifying the hash — specifically its iterator — in multiple threads. You need a lock.

      Ok... I had no idea hash iterators were a thing... I'd always just assumed keys was a read-only function that used local variables to iterate through the hash keys, though that's probably overstating how much thought I've even put into how hashes work under the hood. Thank you, I've used the keys function so long I never would have thought I had an incomplete understanding of how it worked.

      A shared hash in list context (my @a = %testOne) counts as modifying its internal iterator, too? (@a size will get 10,4,12,18 or whatever). And neither such assignment nor keys built-in are "atomic" thread-wise then, and it's not a bug? Yes, using a lock helps. In scalar context it evaluates to 1, not to number of keys. Not documented anywhere, neither.

Re: Inconsistent results with keys on thread shared hashes
by Anonymous Monk on Aug 03, 2022 at 10:42 UTC
      In this instance an array would be the better choice. I chose to complicate a simple part of my code to make a more complex part simpler. While I was debugging this glitch in my code I refactored and reimplemented the genetic sorting algorithm many times, and the current iteration uses a similar technique to what you linked (albeit they did it better, making me wish I'd seen that post earlier). It got to the point that I was absolutely confident that part of the code wasn't the problem, so I started recording the output from my simpler subroutines to track down where the inconsistencies were being generated. I will say, genetic sorting doesn't work all that great when your value function gives different results for the same input.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11145911]
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (2)
As of 2022-08-14 21:31 GMT
Find Nodes?
    Voting Booth?

    No recent polls found