6

I was reading some questions regarding the $@ global variable and how it can be clobbered before it's even handled due to successful evals wiping it clean.

But what if it gets clobbered by an error occurring in a concurrent thread? The new threads package says stuff isn't shared by default, which means it's one of the few mainstream languages that makes '$a = $a;' deterministic by default (and to think that people say C# and Java are better than Perl in large projects). But I'm not sure about special global variables.

My gut's instinct says they're just like any other variable, thus they won't be shared. My brain's instinct says 'let's check with the wizards on Stackoverflow'.

I checked the threading tutorial on Perldoc, and it covers normal variables in the sharing section, but then seems to move on without covering special variables.

Can I use the special variables without risk of them being clobbered by other threads, even if I don't localize them first? E.g. can I pull a value out of $@ without worrying about errors occurring in parallel threads?

Louis
  • 2,442
  • 1
  • 18
  • 15

1 Answers1

6

your guts are right, they are not shared!

salva
  • 9,943
  • 4
  • 29
  • 57
  • Goody, goody. I've started toying around with the threads module after having a few long sessions with Java threads. This is bliss in comparison, but no doubt that thread-local variables have a performance penalty. Should I put locks around external resources in when writing modules to make them thread-safe even if I'm not intending to use it in a thread-safe manner myself? – Louis Jul 19 '11 at 20:53
  • 2
    @Louis: There is no penalty for using thread-local variables. The performance problem with Perl threads is that creating them can be very expensive. Regarding locking external resources, AFAIK, you don't need to lock anything unless you go into XS land. – salva Jul 19 '11 at 21:13
  • 1
    @Louis: You can also run into performance issues when moving data between threads. For example, if using a `Thread::Queue` to pass data around, and each of your threads is calculating a large array, it is often faster to serialize the data into a string (using Storable for example), rather than having the queue recursively convert every member of the data structure into a `threads::shared` variable. But as salva mentions, once the thread is created, thread private variables run at full speed. It is only creating threads and using shared variables that will slow you down. – Eric Strom Jul 19 '11 at 21:25
  • @salva: Yeah, by performance penalty I was referring to the creation of new threads with brand new copies of local data, which seems suspiciously familiar to forking new processes. When I'm talking about external resources, I suppose an example is in order. If, due to poor design, I had a package that used a hard-coded file to read/write persistent data, should I synchronize the access in order to make it thread safe even if I'm not going to be using it myself _at the current moment in time_ from multiple threads? Is it just common courtesy to do so in modern Perl packages? – Louis Jul 19 '11 at 22:57
  • @Eric: So I should avoid performing operations that results in large data structures having to have each member having threads::shared :shared applied to them. OK, got it. So converting complex data to a simple scalar value will speed up general sharing between threads? Sort of makes sense. – Louis Jul 19 '11 at 23:00
  • @Louis => Of course benchmark to be sure (since there is certainly a tipping point at a certain data structure size), but yes if trying to use threads for speed, you need to make sure that your code isn't spending more time managing the threads (which includes setting up threads::shared variables) than you are saving by being multi-threaded. I once wrote a fractal viewer that was rendering slices of the fractal in each thread. Sending the main thread a joined bitmap string was orders of magnitude faster than sending back the array of pixels. – Eric Strom Jul 20 '11 at 01:31
  • 1
    @Louis => more or less, you can use the same rules of efficiency that apply to IPC when dealing with Perl's threads. This is of course because Perl's threads are effectively processes, which is how they operate concurrently across multiple processors, unlike the "green" threads of some other languages. So always favor a few large messages over many small ones. – Eric Strom Jul 20 '11 at 01:45
  • @Eric: So treat shared data as if they were being sent through UNIX pipes :) Got it, thanks for the help. – Louis Jul 20 '11 at 01:52