Perl:跨条件使用平衡的最佳方式

时间:2012-12-17 19:08:37

标签: perl

我有一个有两个条件的脚本(C1和C2)。每次用户登录时,我希望使用严格的平衡(非随机分配)将此用户分配给这两个条件之一,以便将User1(U1)分配给C1,U2分配给C2,U3分配给C1,U4到C2等。

最简单的方法是什么?

现在,我正在考虑这样做:

my $cond;
my $out_cfile = "cfile.txt"; #intial value printed in the file is 1
open(CFILE, "+<", $out_cfile) or die "cannot open $out_cfile";
flock(CFILE, 2);
my $cdata = <CFILE>;
my $last = (substr $cdata,-1,1); #get the latest printed value
if ($last == 1) {$cond = 1; print CFILE "2";}
if ($last == 2) {$cond = 2; print CFILE "1";}
close(CFILE);

print "my condition is: $cond";

有没有办法在不打开和打印到输出文件的情况下执行此操作?

3 个答案:

答案 0 :(得分:0)

我使用绑定哈希,但如果你想要线程安全,你需要实现某种形式的互斥,也许是一个信号量。

答案 1 :(得分:0)

最简单的方法是使用lock警告:未经测试,但这样的事情应该有效):

use strict;
use warnings;
use threads;
use threads::shared;
use Thread::Queue;

my $num_users_logged_in :shared = 1;

my $num_watcher_threads = 1; #it may make sense to make this larger, maybe not. 

my @users = (); #populate array of users that are logging in.

my $queue = Thread::Queue->new;

$queue->enqueue(@users);

my @threads = ();

foreach(1..$num_watcher_threads)
{
  push @threads, threads->create(\&log_in);
}

# NOTE: If you ever want this program to stop, 
# then you'll have to enqueue some undefs (one for each thread).

# Waiting for each of the threads to finish.
# If you don't want to do this, then detach() instead
$_->join() foreach(@threads);

#Do anything else that you want after all of the threads are done.

sub log_in
{
  #Threads will block until it grabs an undef in the queue
  while(my $user = $queue->dequeue)
  {
    #Do whatever you need to do before locking the variable.
    {
      lock $num_users_logged_in;
      #Other threads will block until we're done with this block of code.

      #Assign conditions based upon the parity of $num_users_logged_in
      #And do whatever else you need for that particular user

      $num_users_logged_in++;
    }
  }
}

答案 2 :(得分:0)

我真的不明白在/tmp目录中创建文件的难度,或者如果它尚不存在,那么你可以使用memcached

use Cache::Memcached qw( );

my $memd = Cache::Memcached->new({
   server    => [ '127.0.0.1:11211' ],
   namespace => 'app_name:',
});

my $val = $memd->incr('counter');
if ($val % 2) {
   ...
} else {
   ...
}

incr以原子方式递增和提取以避免竞争条件(因此它与您的代码一样安全)。