in reply to Slow worker threads

This is not related to your performance problem, but I wonder if flock is doing what you think it is. Consider the following:

use strict; use warnings; use threads; use Fcntl qw(:flock); open(FILE, ">>/tmp/test.txt"); for(0..9) { threads->new(\&worker, $_); } $_->join for threads->list; sub worker { my $x = shift; flock(FILE, LOCK_EX); print "$x: locked file\n"; sleep(10); flock(FILE, LOCK_UN); print "$x: unlocked file\n"; return; }

Which produces

0: locked file 1: locked file 2: locked file 3: locked file 4: locked file 5: locked file 6: locked file 7: locked file 8: locked file 9: locked file 0: unlocked file 1: unlocked file 2: unlocked file 3: unlocked file 4: unlocked file 5: unlocked file 6: unlocked file 7: unlocked file 8: unlocked file 9: unlocked file

If you are locking against other processes changing the file between your writes, you should probably be seeking to end of file between locking and writing.

Replies are listed 'Best First'.
Re^2: Slow worker threads
by spx2 (Deacon) on Jul 18, 2009 at 17:56 UTC

    Let's consider NONBLOCKING flock , there's something really wrong going on :

    use strict; use warnings; use threads; use feature 'say' ; use Fcntl qw(:flock); open(FILE, ">>/tmp/test.txt"); for(0..9) { threads->new(\&worker, $_); } $_->join for threads->list; sub worker { my $x = shift; my $locked; $locked = flock(FILE, LOCK_EX|LOCK_NB ); if( $locked ) { say "$x: lock acquired"; sleep 4; } else { say "$x: cannot acquire lock"; } flock( FILE, LOCK_UN ); print "$x: lock released\n"; return; }
    0: lock acquired 1: lock acquired 2: lock acquired 3: lock acquired 4: lock acquired 5: lock acquired 6: lock acquired 7: lock acquired 8: lock acquired 9: lock acquired 0: lock released 1: lock released 2: lock released 3: lock released 4: lock released 5: lock released 6: lock released 7: lock released 8: lock released 9: lock released

    How come the lock is acquired again and again without being released anywhere in between ?!

    Isn't this what a lock is supposed to do ? Lock something and not give access to anyone else until released ?

      it didn't occur to me that the threads were actually sharing the FILE filehandle , so if one acquired the lock , each of them actually acquired the lock because FILE was shared amongst them( thanks tye for pointing that out )

      I managed to pull of a quick replacement for that which works as one would expect.

      Notice the 9-$x , that is to make sure that time(thread1)>time(thread2)>time(thread3)>... .

      Also notice that $thread_lock are thread-specific locks

      use strict; use warnings; use threads; use feature 'say' ; use Fcntl qw(:flock); my $file_path = ">>/tmp/test.txt"; open(FILE, $file_path); for(0..9) { threads->new(\&worker, $_); } $_->join for threads->list; sub worker { my $x = shift; my $locked; open(my $thread_lock,$file_path); $locked = flock($thread_lock, LOCK_EX|LOCK_NB ); if( $locked ) { say "$x: lock acquired"; sleep 9-$x; } else { say "$x: cannot acquire lock"; }; if($locked) { flock( $thread_lock, LOCK_UN ); print "$x: lock released\n"; } return; }
      0: lock acquired 1: cannot acquire lock 2: cannot acquire lock 3: cannot acquire lock 4: cannot acquire lock 5: cannot acquire lock 6: cannot acquire lock 7: cannot acquire lock 8: cannot acquire lock 9: cannot acquire lock 0: lock released