[ Perl ] 多线程并发编程
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;
参考资料/拓展
- threads - Perl interpreter-based threads - metacpan.org
- threads::shared - Perl extension for sharing data structures between threads - metacpan.org
- Thread::Queue - Thread-safe queues - metacpan.org
- Thread::Semaphore - Thread-safe semaphores - metacpan.org
- Thread::Pool - group of threads for performing similar jobs - metacpan.org
[ Perl ] 多线程并发编程的更多相关文章
- Java 多线程并发编程一览笔录
Java 多线程并发编程一览笔录 知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run ...
- 【收藏】Java多线程/并发编程大合集
(一).[Java并发编程]并发编程大合集-兰亭风雨 [Java并发编程]实现多线程的两种方法 [Java并发编程]线程的中断 [Java并发编程]正确挂起.恢复.终止线程 [ ...
- java多线程并发编程与CPU时钟分配小议
我们先来研究下JAVA的多线程的并发编程和CPU时钟振荡的关系吧 老规矩,先科普 我们的操作系统在DOS以前都是单任务的 什么是单任务呢?就是一次只能做一件事 你复制文件的时候,就不能重命名了 那么现 ...
- Java基础系列篇:JAVA多线程 并发编程
一:为什么要用多线程: 我相信所有的东西都是以实际使用价值而去学习的,没有实际价值的学习,学了没用,没用就不会学的好. 多线程也是一样,以前学习java并没有觉得多线程有多了不起,不用多线程我一样可以 ...
- Java 多线程并发编程
导读 创作不易,禁止转载! 并发编程简介 发展历程 早起计算机,从头到尾执行一个程序,这样就严重造成资源的浪费.然后操作系统就出现了,计算机能运行多个程序,不同的程序在不同的单独的进程中运行,一个进程 ...
- Java多线程并发编程/锁的理解
一.前言 最近项目遇到多线程并发的情景(并发抢单&恢复库存并行),代码在正常情况下运行没有什么问题,在高并发压测下会出现:库存超发/总库存与sku库存对不上等各种问题. 在运用了 限流/加锁等 ...
- java多线程并发编程
Executor框架 Executor框架是指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括线程池,Executor,Executors,ExecutorService ...
- Java多线程并发编程一览笔录
线程是什么? 线程是进程中独立运行的子任务. 创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法 方式二:声明实现 Runnable 接口的类.该 ...
- Java 多线程并发编程面试笔录一览
知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法 方式二:声明实现 Runn ...
随机推荐
- 网络监听HTTP协议信息实验
一.开启环境 登录web服务器,在服务器中开启phpstudy服务器环境. 在操作机中打开目标站[Web服务器IP地址]地址.安装wordpress,数据库名:wordpress,用户名root 密码 ...
- uoj450 【集训队作业2018】复读机(生成函数,单位根反演)
uoj450 [集训队作业2018]复读机(生成函数,单位根反演) uoj 题解时间 首先直接搞出单个复读机的生成函数 $ \sum\limits_{ i = 0 }^{ k } [ d | i ] ...
- 由浅入深,带你用JavaScript实现响应式原理(Vue2、Vue3响应式原理)
由浅入深,带你用JavaScript实现响应式原理 前言 为什么前端框架Vue能够做到响应式?当依赖数据发生变化时,会对页面进行自动更新,其原理还是在于对响应式数据的获取和设置进行了监听,一旦监听到数 ...
- VUE常见问题
VUE常见问题 对于MVVM的理解 MVVM 是 Model-View-ViewModel 的缩写 Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑 View 代表UI 组件, ...
- JVM知识(一) 求你了,别再说Java对象都是在堆内存上分配空间的了!
求你了,别再说Java对象都是在堆内存上分配空间的了! https://baijiahao.baidu.com/s?id=1661296872935371634&wfr=spider& ...
- ruoyi首次使用常见问题的解决方案
1.导入项目之后,下载依赖包之后,模块的依赖项飘红(我这里无法复现,当参考图吧) 解决方法: 2.ruoyi框架代码生成之后,需要自己进行替换到指定位置.相应的官方文档位置,否则,可能会出现404,访 ...
- Java 中 ConcurrentHashMap 的并发度是什么?
ConcurrentHashMap 把实际 map 划分成若干部分来实现它的可扩展性和线程安 全.这种划分是使用并发度获得的,它是 ConcurrentHashMap 类构造函数的一 个可选参数,默认 ...
- XMLBeanFactory?
最常用的就是org.springframework.beans.factory.xml.XmlBeanFactory ,它根据XML文件中的定义加载beans.该容器从XML 文件读取配置元数据并用它 ...
- ZAB 协议?
ZAB 协议是为分布式协调服务 Zookeeper 专门设计的一种支持崩溃恢复的原子广 播协议. ZAB 协议包括两种基本的模式:崩溃恢复和消息广播. 当整个 zookeeper 集群刚刚启动或者 L ...
- ReentrantLock 源代码之我见
ReentrantLock,英文意思是可重入锁.从实际代码实现来说,ReentrantLock也是互斥锁(Node.EXCLUSIVE).与互斥锁对应的的,还有共享锁Node.SHARED Reent ...