perl程序中的多线程在Windows上产生意外结果

时间:2012-10-16 11:39:58

标签: multithreading perl

我是perl的新手并尝试多线程。我期待以下程序创建所有线程并至少在5秒后打印“创建所有线程”,一旦执行并且所有线程都在等待输入值。

use threads;

my @arr = (1,2,3,4);
foreach (@arr) {
    sleep(1);
    print "\ncreating...\n";
    threads->new(\&echo, $_);
    print "\ncreated\n";
}
print "\ncreated all the threads\n";
sleep(200); #wait for the threads to finish

sub echo {
    my ($thread) = @_;
    print "\nthread($thread) Enter the value:\n";
    my $value = <>;
    print "\nthread($thread) Got value= $value\n";
}

但是我正在关注:

creating...

created

thread(1) Enter the value:

creating...

似乎还没有创建其他3个线程,如果我移除睡眠(1)我得到有时预期的结果,但是涉及睡眠(1),甚至等待几分钟,我得到上述结果。我可能缺少什么?我认为这是基本的,但我无法弄明白。

更新:

同样的程序在Linux上完美无缺,可能是Windows的平台特定问题?

UPDATE2:

在同一行上的以下java程序可以在同一个盒子上正常工作:

import java.io.IOException;


public class MT {

    public static void main(String[] args)throws Exception {
        for(int i=0;i<4;i++){
            Thread.sleep(2000);
            new Thread(new Task(i)).start();
        }
        System.out.println("created all the threads");
        Thread.sleep(20000);

    }

    static class Task implements Runnable{

        int i;
        public Task(int i) {
            super();
            this.i = i;
        }
        @Override
        public void run() {
            try {
                System.out.println("Thread:"+i+" Enter value");
                int x= System.in.read();
                System.out.println(x);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

我不确定perl如何在windows上支持多线程!

1 个答案:

答案 0 :(得分:2)

您实际上有两种不同的阻止问题:

  1. 在控制台上进行I / O缓冲(感谢Disco 3提供此建议)。
  2. 从标准输入块读取的线程相互阻塞(但不是其他线程)。
  3. 考虑这个测试程序:

    use threads;
     $| = 1;
    
    my $thr1 = threads->new(\&echo, 1);
    my $thr2 = threads->new(\&print_dots, 2);
    sleep 10;
    my $thr3 = threads->new(\&echo, 3);
    
    sleep 200;
    
    
    
    sub print_dots {
        while (1) {
            print ".";
            sleep 1;
        }
    }
    
    sub echo {
    
        my ($thread) = @_;
        print "\nthread($thread) Enter the value:\n";
        sleep 1;
        my $value = <>;
        print "\nthread($thread) Got value= $value\n";
    }
    

    如果您不禁用i / o缓冲(由$|=1;完成),那么您根本不会得到任何点。如果禁用输入缓冲,则永远不会阻止打印点的线程。但是,从控制台读取的第二个线程仍然被第一个阻塞。

    如果您需要在Windows上使用Perl中的标准输入进行真正的非阻塞读取,那么有一些潜在的解决方案。 Win32::Console可能是一个很好的起点。 Here is a potentially useful discussion