2012-05-09 3 views
3

자바에서는 스레드를 만들고 객체를 공유하는 동안 동일한 객체 메소드에 액세스하는 스레드를 원할 때가 있습니다. 그러나 동시에 그 객체를 수행하지는 않습니다. 그래서 이것을 피하기 위해 아래와 같이 객체 메소드를 Synchronized 메소드로 정의 할 것입니다.펄에서 동기화 된 방법을 만드는 방법은 무엇입니까?

동기화 인스턴스 방법 :

CLASS_NAME 클래스 { 동기 형 METHOD_NAME() { \ 문 블록 } }

방법의 모든 문은 동기화 된 블록되고, 인스턴스 객체 인 자물쇠. 즉,이 메서드를 사용하도록 스레드에 알리면 이전 스레드가 메서드를 사용하여 끝날 때까지 대기합니다. Perl에서이를 수행 할 수있는 방법이 있습니까?

답변

2

스레드간에 신호를 보내려면 semaphores을 사용하고, 문제의 메서드가 호출 될 때 lock 공유 개체를 사용하면 잠금 스레드가 해당 메서드 호출을 완료 할 때까지 다른 스레드의 이후 호출을 차단할 수 있습니다. 내가보기 엔 펄의 스레드로 perl thread tutorial을 통해 읽어 보시기 바랍니다 수 펄에서 스레딩을 시작하기 전에

생성자에서 뮤텍스를 만들기 다른 언어

5

다릅니다.

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

입력 할 때 잠급니다.

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

데모 : 동시에 $o1->method 실행에

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$o2->method은 동시에 실행할 수 있습니다. 당신이 — 어쨌든 객체를 공유 할 거라면

사실이 그가 코드 — 위에 당신이 잠금으로 객체 자체를 사용할 수 async INT에 인수로 객체를 전달하여 이루어졌다.

use threads::shared qw(shared_clone); 

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

입력 할 때 잠급니다. (5.005)에서

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

이미 매우 간단했지만, 심지어 더 간단합니다. – ikegami

+0

실제로 위의 코드에서 threads :: shared :: shared_clone을 지정해야합니다. 그렇지 않으면 shared_clone이 패키지에 없으므로 오류가 발생합니다. 귀하의 예제는 클래스를 정의하기 위해 패키지를 지정하는 것을 게을리하여 코드가 실제로 객체 지향적이 아니기 때문에 작동합니다. – CDahn

+0

@CDahn, 아니요,'use threads :: shared qw (shared_clone); '을 사용하여 가져올 수 없습니다. 나는 이것을 추가했다. /// 당신은 착각을합니다; 나는 클래스를 정의했고 그 클래스의 객체를 만들었습니다. – ikegami

0

오래된 펄 스레딩 모델은 더 또는 덜 당신이 원하는 무엇 속성 :locked을 지원했다. 그러나 현재 ithreads 모델 (5.8 이상)의 경우 유사한 특성을 다시 도입 할 수 있습니다.그래서 같은

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 { 
    ... 
} 

그리고 코드 :

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__; 
} 

당신과 같이 클래스를 쓸 수 있도록 허용 : 구문 Attribute::Handlers의 편리 성 뒤에 숨겨진

이 이케 가미의 simplified solution @ 본질적으로,

$foo_object->method_name(); # Don't worry, it's synchronized! 
관련 문제