How to make a synchronized method in perl?

In Java, when I create threads and share an object, there are times when I want threads to access the same object, but I do not do them at the same time. Thus, to avoid this, I will define the method of the object as a synchronous method, as shown below.

Synchronous Instance Method:

class class_name {synchronized type method_name () {\ statement block}}

All statements in the method become a synchronized block, and the instance is a lock. This means that if I talk about a thread to use this method, it will wait until the previous thread finishes using this method. Is there any way to do this in Perl?

+3
source share
3

.

sub new {
   ...
   my $mutex :shared;
   $self->{mutex_ref} = \$mutex;
   ...
}

.

sub method {
   my ($self) = @_;
   lock ${ $self->{mutex_ref} };
   ...
}

:

use strict;
use warnings;
use threads;
use threads::shared;
use feature qw( say );

sub new {
   my ($class, $id) = @_;
   my $mutex :shared;
   return bless({
      mutex_ref => \$mutex,
      id        => $id,
   }, $class);
}

sub method {
   my ($self) = @_;
   lock ${ $self->{mutex_ref} };
   say sprintf "%08X %s %s", threads->tid, $self->{id}, "start";
   sleep(2);
   say sprintf "%08X %s %s", threads->tid, $self->{id}, "end";
}

my $o1 = __PACKAGE__->new('o1');
my $o2 = __PACKAGE__->new('o2');

for (1..3) {
   async { my ($o) = @_; $o->method() } $o1;
   async { my ($o) = @_; $o->method() } $o2;
}

$_->join for threads->list();
  • $o1->method .
  • $o1->method $o2->method .

, , async int he above code — .

use threads::shared qw( shared_clone );

sub new {
   my ($class, ...) = @_;
   return shared_clone(bless({
      ...
   }, $class));
}

.

sub method {
   my ($self) = @_;
   lock %$self;
   ...
}
+5
+2

The old perl streaming model (from 5.005) supports an attribute :lockedthat does more or less what you want. However, for the current ithreads model (5.8), you can re-enter the same attribute.

This is essentially a simplified @ikegami solution hidden behind syntactic convenience Attribute :: Handlers :

package Local::Sub::Attribute::Synchronized;
use strict;
use warnings;
use thread::shared;
use Attribute::Handler;

sub Synchronized : ATTR(CODE) {
  my (undef, $sym, $code) = @_;
  #
  # Lock the first argument (assumed to be a shared() object), then call $code
  # with the original @_
  #
  no warnings 'redefine';
  *{$sym} = sub { lock($_[0]); &$code; };
}

sub import {                              # Make :Synchronized available to our importer.
  my $callpkg = caller;                   # The usual technique is defines a UNIVERSAL::
  no strict 'refs';                       # handler, but I find that a bit ham-fisted.
  push @{"${callpkg}::ISA"}, __PACKAGE__;
}

Allows you to write your classes as follows:

package Foo;
use threads::shared;
use Local::Sub::Attribute::Synchronized;

sub new { shared_clone(...); }     # N.B.:  Your Foo object must be shared!

sub method_name : Synchronized {
  ...
}

And your code looks like this:

$foo_object->method_name();  # Don't worry, it synchronized!
0
source

All Articles