in reply to Re^5: multithreads newbie question
in thread multithreads newbie question

You should create your variables shared. Sharing objects doesn't really make sense unless the object is specifically designed to transport data between threads. Either special purpose objects, or don't use objects at all to exchange data.

Replies are listed 'Best First'.
Re^7: multithreads newbie question
by daverave (Scribe) on Aug 11, 2010 at 06:39 UTC
    Oh... I don't get it. All of these subs are within the same object. Each of them does some changes to the object state (e.g. add stuff to $self).

    Can't I make $self shared? I don't really understand what is the alternative?

    Here is a simple example (following the previous one):

    obj.pm:

    package obj; use 5.010; use strict; use threads; use Thread::Queue qw( ); sub new { my ( $class, %args ) = @_; my $self = bless( {}, $class ); say "creating new obj"; return $self; } sub sub1 { say "sub1 starts"; sleep 1 for 1 .. 2; say "sub1 ends" } sub sub2 { my $self = shift; $self->{KEY} = 1; exists( $self->{KEY} ) ? say "KEY exists" : say "KEY does NOT exis +t"; say "sub2 starts"; sleep 1 for 1 .. 2; say "sub2 ends"; } sub sub3 { say "sub3 starts"; sleep 1 for 1 .. 5; say "sub3 ends" } sub sub4 { say "sub4 starts"; sleep 1 for 1 .. 5; say "sub4 ends" } sub sub5 { say "sub5 starts"; sleep 1 for 1 .. 5; say "sub5 ends" } sub sub6 { say "sub6 starts"; sleep 1 for 1 .. 5; say "sub6 ends" } sub sub7 { say "sub7 starts"; sleep 1 for 1 .. 2; say "sub7 ends" } sub sub8 { say "sub8 starts"; sleep 1 for 1 .. 2; say "sub8 ends" } sub run { my $self = shift; my $q = Thread::Queue->new(); my $t1 = async { sub1(); $q->enqueue(1); }; my $t2 = async { sub2($self); $q->enqueue(2); }; my $pending = 2; my @threads; for ( ; ; ) { my $id = $q->dequeue(); if ( $id == 1 ) { $t1->join(); push @threads, async { sub3() }, async { sub4() }; --$pending; } elsif ( $id == 2 ) { $t2->join(); exists( $self->{KEY} ) ? say "KEY exists" : say "KEY does NOT exist"; push @threads, async { sub5() }, async { sub6() }; --$pending; } if ( !$pending ) { push @threads, async { sub7() }, async { sub8() }; last; } } $_->join() for @threads; } 1;

    test.pl:

    use strict; use warnings; use obj; my $o = obj->new(); $o->run();

      Yes, you can. See the section on objects.

      But it's gonna lead to very messy code. You'd need to lock the object every time you'd use it. If the object has multiple attributes, that could lead to spaghetti code really fast.

      It's much better if you lay down the code as inputs → process → outputs.

        Why do I have to lock the object every time I use it? If I know that sub1 only changes $self->{KEY1} and sub2 only changes $self->{KEY2}, and both do not depend on the keys the other changes, do I still have to lock the object?

        Can you please elaborate just a bit on what you wrote on the last line?