https://www.cnblogs.com/yeungchie/

记录一些常用的 模块 / 方法 。

多线程

使用模块 threads

use 5.010;
use threads; sub func {
my $id = shift;
sleep 1;
print "This is thread - $id\n";
}

创建线程

  • new
sub start {
my $id = shift;
my $t = new threads \&func, $id;
return $t;
}
  • create
sub start {
my $id = shift;
my $t = new threads \&func, $id;
return $t;
}
  • async
sub start {
my $id = shift;
my $t = async { &func( $id ) };
return $t;
}

线程收尸

  • 阻塞 join
&start( 'join' )->join;
say 'Done';

This is thread - join

Done

# 父线程被子线程阻塞,成功收尸。

  • 非阻塞 detach
&start( 'detach' )->detach;
say 'Done';

Done

# 由于非阻塞,父线程已经退出,子线程变成孤儿线程,无法收尸。

数据共享

使用模块 threads::shared

use threads::shared;

标记共享变量

有几种不同的写法

  • 依次标记 :shared
my $scalar :shared;
my @array :shared;
my %hash :shared;
  • 批量标记 :shared
my ( $scalar, @array, %hash ) :shared;
  • 用函数标记 share()
my ( $scalar, @array, %hash );
share $scalar;
share @array;
share %hash;

克隆 shared_clone

向共享的变量中加入新的元素时,需要注意的地方。

my @newArray = qw( YEUNG CHIE 1 2 3 );
my $clone = shared_clone [@newArray];
push @array, $clone;
$hash{ keyName } = $clone;

lock

多个线程同时编辑一个共享变量时,需要注意的地方。

经典的取钱问题:

1 - 输出额度 $amount = 500

2 - func() 函数模拟取钱,每次取 300

3 - 当 $amount < 300 时,则无法取钱

  • 没加锁的情况
my $amount :shared = 500;

sub func {
unless ( $amount < 300 ) {
sleep 1; # 睡眠一秒模拟延迟
$amount -= 300;
}
} # 这里两个线程模拟,两次取钱同时进行
my $t1 = new threads \&func;
my $t2 = new threads \&func;
$t1->join;
$t2->join; say $amount;

-100

# 结果被取了两次,剩余额度为 -100

  • 加了锁的情况

调整一下子函数 func(), 加个锁。

...
sub func {
lock $amount;
unless ( $amount < 300 ) {
sleep 1;
$amount -= 300;
}
}
...

200

# 结果正确

线程队列

使用模块 Thread::Queue

use Thread::Queue;

创建队列

my $queue = new Thread::Queue;

入队 enqueue

my $var = 'YEUNG';
$queue->enqueue( $var );
$queue->enqueue( qw( CHIE 1 2 3 ) );

出队 dequeue

  • 默认出队一个项目
say $queue->dequeue;

YEUNG

  • 指定多个项目出队
say for $queue->dequeue( 3 );

CHIE

1

2

非阻塞出队 dequeue_nb

  • 如果是阻塞出队
my $queue = new Thread::Queue qw( YEUNG CHIE );
say while $_ = $queue->dequeue;

YEUNG

CHIE

# 程序会卡在这里,等待队列中新的项目加入

  • 使用非阻塞出队
my $queue = new Thread::Queue qw( YEUNG CHIE );
say while $_ = $queue->dequeue_nb;

YEUNG

CHIE

剩余 pending

pending 方法可以返回未出队的项目数量。

my $queue = new Thread::Queue qw( YEUNG CHIE );
say $queue->dequeue;
say $queue->pending;
say $queue->dequeue;
say $queue->pending;

YEUNG

1

CHIE

0

查看 peek

只是看看但是不出队。

my $queue = new Thread::Queue qw( YEUNG CHIE );
say $queue->peek;
say $queue->pending;
say $queue->peek( 2 );
say $queue->pending;

YEUNG

2

CHIE

2

入队结束 end

除了上面用 dequeue_nb 非阻塞出队,之外还可以用 end 方法来

my $queue = new Thread::Queue qw( YEUNG CHIE );
$queue->end;
say while $_ = $queue->dequeue;

# 这样虽然没有用 dequeue_nb 方法,程序也不会卡住了。

不过这个方法需要模块版本 >= 3.01,一般系统自带 Perl 是不支持的,但是我们也可以自己来实现这个效果:

  • 共享变量

    共享一个全局变量标记入队结束。

    my $endFlag :shared;
  • 生产者线程

    当入队结束时,$endFlag 赋值为真。

    $endFlag = 1;
  • 消费者线程

    循环操作非阻塞出队。

    while ( 1 ) {
    my $item = $queue->dequeue_nb;
    if ( defined $item ) {
    say $item;
    }
    else {
    # 当出队失败且入队结束时,退出循环
    last if $endFlag;
    }
    }

线程信号量

使用模块 Thread::Semaphore

use Thread::Semaphore;

线程池

使用模块 Thread::Pool

use Thread::Pool;

参考资料/拓展

[ Perl ] 多线程并发编程的更多相关文章

  1. Java 多线程并发编程一览笔录

    Java 多线程并发编程一览笔录 知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run ...

  2. 【收藏】Java多线程/并发编程大合集

    (一).[Java并发编程]并发编程大合集-兰亭风雨    [Java并发编程]实现多线程的两种方法    [Java并发编程]线程的中断    [Java并发编程]正确挂起.恢复.终止线程    [ ...

  3. java多线程并发编程与CPU时钟分配小议

    我们先来研究下JAVA的多线程的并发编程和CPU时钟振荡的关系吧 老规矩,先科普 我们的操作系统在DOS以前都是单任务的 什么是单任务呢?就是一次只能做一件事 你复制文件的时候,就不能重命名了 那么现 ...

  4. Java基础系列篇:JAVA多线程 并发编程

    一:为什么要用多线程: 我相信所有的东西都是以实际使用价值而去学习的,没有实际价值的学习,学了没用,没用就不会学的好. 多线程也是一样,以前学习java并没有觉得多线程有多了不起,不用多线程我一样可以 ...

  5. Java 多线程并发编程

    导读 创作不易,禁止转载! 并发编程简介 发展历程 早起计算机,从头到尾执行一个程序,这样就严重造成资源的浪费.然后操作系统就出现了,计算机能运行多个程序,不同的程序在不同的单独的进程中运行,一个进程 ...

  6. Java多线程并发编程/锁的理解

    一.前言 最近项目遇到多线程并发的情景(并发抢单&恢复库存并行),代码在正常情况下运行没有什么问题,在高并发压测下会出现:库存超发/总库存与sku库存对不上等各种问题. 在运用了 限流/加锁等 ...

  7. java多线程并发编程

    Executor框架 Executor框架是指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括线程池,Executor,Executors,ExecutorService ...

  8. Java多线程并发编程一览笔录

    线程是什么? 线程是进程中独立运行的子任务. 创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法 方式二:声明实现 Runnable 接口的类.该 ...

  9. Java 多线程并发编程面试笔录一览

    知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法 方式二:声明实现 Runn ...

随机推荐

  1. Linux服务器上搭建Centos7.0+Apache+php+Mysql网站

    一.安装Linux系统 1.1虚拟机搭建Linux Centos7.0版本,搭建过程省略. 二. 安装apache.php.mysql.php-gd等组件. 2.1安装Apache服务程序(apach ...

  2. XSS 32个触发事件

    标签: 1.onmouseenter:当鼠标进入选区执行代码 <div style="background-color:red" onmouseenter="ale ...

  3. 西门子S210电机位置控制过调问题解决方法

    问题描述 创建完工艺对象,使用MC_MoveAbsolute工艺指令进行绝对定位,发现在下达指令后,电机会出现先超过目标位置再回调的现象,即过冲. 电机连接的机械结构为旋转轴,而不是线性轴. 解决方法 ...

  4. 手把手带你使用Paint in 3D和Photon撸一个在线涂鸦画板

    Paint in 3D Paint in 3D用于在游戏内和编辑器里绘制所有物体.所有功能已经过深度优化,在WebGL.移动端.VR 以及更多平台用起来都非常好用! 它支持标准管线,以及 LWRP.H ...

  5. java继承:extends

    继承:extends 1.java只支持单继承,不支持多继承 2.java支持多层继承(继承体系) 3.子类不能继承父类所有非私有的成员(成员方法和成员变量) 4.子类不能继承父类的构造方法,但是可以 ...

  6. 怎么得到InnoDB主键索引B+树的高度?

    上面我们通过推断得出B+树的高度通常是1-3,下面我们从另外一个侧面证明这个结论.在InnoDB的表空间文件中,约定page number为3的代表主键索引的根页,而在根页偏移量为64的地方存放了该B ...

  7. 转载:23种常用设计模式的UML类图

    转载至:https://www.cnblogs.com/zytrue/p/8484806.html 23种常用设计模式的UML类图 本文UML类图参考<Head First 设计模式>(源 ...

  8. Java 线程数过多会造成什么异常?

    1.线程的生命周期开销非常高 2.消耗过多的 CPU 资源 如果可运行的线程数量多于可用处理器的数量,那么有线程将会被闲置.大量空 闲的线程会占用许多内存,给垃圾回收器带来压力,而且大量的线程在竞争  ...

  9. MyBatis Plus 2.3 个人笔记-01-代码生成器

    sb_mybatis_puls2.3 <?xml version="1.0" encoding="UTF-8"?> <project xmln ...

  10. Spring官宣网传大漏洞,并提供解决方案

    Spring沦陷了!这样的标题这几天是不是看腻了?然而,仔细看看都是拿着之前的几个毫不相干的CVE来大吹特吹.所以,昨天发了一篇关于最近网传的Spring大漏洞的文章,聊了聊这些让人迷惑的营销文.以及 ...