2015-10-08 3 views
7

Я пытаюсь написать простой скрипт, который использует потоки и разделяет переменную, но я не хочу превращать эту переменную глобальную в весь скрипт. Ниже приведен упрощенный пример.Совместное использование переменной потока без ее глобального (Perl)

use strict; 
use warnings; 
use threads; 
use threads::shared; 

my $val:shared; 

# Create threads 
for my $i (1 .. 5) { 
    threads->create(\&do_something, $i); 
} 

# Wait for all threads to complete 
map { $_->join(); } threads->list(); 

# $val is global to the script so this line will work! 
print "VAL IS: $val\n"; 

sub do_something { 
    my $i = shift; 
    print "Doing something with thread $i!\n"; 

    { 
     lock $val; 
     $val = "SOMETHING IS $i"; 
     print "$val\n\n"; 
    } 
} 

Выход:

Делая какие-нибудь с резьбой 1! SOMETHING IS 1

Выполнение чего-либо с резьбой 2! SOMETHING IS 2

Выполнение чего-либо с резьбой 3! SOMETHING IS 3

Выполнение чего-либо с резьбой 4! SOMETHING IS 4

Выполнение чего-либо с резьбой 5! ЧТО-ТО ЕСТЬ 5

VAL IS: Что-то 5


Как я могу получить этот эффект, не делая $val доступным для всего сценария? Другими словами, как я могу это сделать, поэтому попытка печати VAL IS: $val завершится с ошибкой, но переменная по-прежнему будет успешно разделяться потоками?


Я не могу определить это так:

# Create threads 
for my $i (1 .. 5) { 
    my $val:shared; 
    threads->create(\&do_something, $i); 
} 

Или получите:

Глобальный символ "$ Вэл" требует явного пакета

Каков правильный способ лексической реализации общей переменной?

+0

Если вы не проходя его, как мог нить как совместно (глобальный), а не глобальный? Кажется, что вы хотите создать слой для своей области. Также вы пытались использовать 'our ($ val);'? – vol7ron

+1

Side-note, 'map {$ _-> join(); } threads-> list(); '=>' $ _-> join() для threads-> list(); 'чтобы ваши намерения были четкими. –

+0

@ Сухой27, спасибо, это немного яснее. – tjwrona1992

ответ

4

Передайте ссылку на него в качестве аргумента.

sub do_something { 
    my ($id, $lock_ref) = @_; 
    print("$id: Started\n"); 
    { 
     lock $$lock_ref; 
     print("$id: Exclusive\n"); 
     sleep(1); 
    } 
    print("$id: done.\n"); 
} 

{ 
    my $lock :shared; 
    for my $id (1..5) { 
     async { do_something($id, \$lock); }; 
    } 
} 

Или его охватить, так что только работники могут его увидеть.

{ 
    my $lock :shared; 

    sub do_something { 
     my ($id) = @_; 
     print("$id: Started\n"); 
     { 
     lock $lock; 
     print("$id: Exclusive\n"); 
     sleep(1); 
     } 
     print("$id: done.\n"); 
    } 
} 

for my $id (1..5) { 
    async { do_something($id); }; 
} 
4

Вы можете ограничить область разделяемой переменной (убедитесь, что Perl видит общую переменную до создания потока),

# .. 
{ 
    my $val:shared; 
    sub do_something { 
     my $i = shift; 
     print "Doing something with thread $i!\n"; 

     { 
      lock $val; 
      $val = "SOMETHING IS $i"; 
      print "$val\n\n"; 
     } 
    } 
} 

# Create threads 
for my $i (1 .. 5) { 
    threads->create(\&do_something, $i); 
} 

# ...