大家的电脑应该都是大等于2核的了,但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行,微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。

拿平时大家写的 for 循环举例。像 go 你可以写两个 go 每个里面各写一个循环同时输入,你可以看到输出是交替。在过去的php版本中,如果只开启一个 cli 写多个 for 循环,那么他的输出一定是顺序的。无法做到交叉输出(也就是无法在第一个循环中执行若干次后,让b再执行,b执行一段时间后,再让A执行)。现在借助 fiber 我们也可以实现这种操作。下面这段代码就可以做到两个循环交叉执行。甚至可以控制两个程序执行的频率(比如A执行3次,B执行一次这样分配)

阅读全文 »

阅读全文 »

前两天写了写了一篇关于go无法捕获panic的的情况。当时并没有想太多,今天突然想到如果我在 gin 的控制器函数中使用了 go 并抛出了 panic 那么会不会被捕获呢?。代码如下

1
2
3
4
5
6
7
8
9
func About(c *gin.Context) {
go func() {
time.Sleep(time.Second * 10)
panic("嘿嘿")
}()
c.JSON(http.StatusOK, gin.H{
"message": "Hello~ Now you see a json from gin",
})
}

结论是请求后10s后就抛出了panic。gin 之所以可以捕获 action 中直接跑出的 panic 是因为 gin 采用的洋葱设计,在外层有着对 panic 的捕获操作。 不同的是,由 go 运行并抛出的 panic 是不会被捕获的。对于这种情况,可以用高阶高数处理一下。不过 子协程 的影响还是比较大的。比如引入的包开了一个 goroutine 但是并没有处理内部的 panic 那么就会让程序产生无法控制的中断。 高阶函数的部分如下

阅读全文 »

1
2
3
4
5
6
7
8
9
10
11
12
func action(){
defer func() {
if r := recover(); r != nil {
log.Println("get panic",r)
}
}()
go func(){
time.Sleep(time.Second*10)
panic(1)
}()
fmt.Println("end")
}

可以这样理解,go的代码和 action 已经是两个世界的东西了。所以即使在主进程也无法捕获。从另一个方面来说,这个方法的 defer 早就已经执行结束了。在fmt.Println("end")后,就已经执行。所以如果要捕获这个 panic 要在他的父函数或者本函数,而不是主进程。

阅读全文 »

今天看到一篇有关channel的问答。文章中中提到了channel的缓存区,当时我看到缓存区的反应是 是不是可以把我之前写的队列用 channel 进行替换。随着 channel 的研究,发现水很深。相对于不要通过共享内存来通信,要通过通信来共享内存这句看似简单的话,使用起来存在的问题还是不少的。

阅读全文 »

这是去年12月,我写在 workman 论坛为 webman windows 下开发热重载的一个脚本,今天在自己博客记录一下。

参考的官网下面的例子,思路和我一开始说的差不多,就是获取pid,然后cmd去kill掉它。proc_open 创建的资源可以直接从父进程中获取执行的pid,所以在不借助其他中间媒介的情况下使用kill命令去kill程序。因为是proc_open是非阻塞的,所以也不会阻挡监控 https://www.php.net/manual/zh/function.proc-terminate.php

阅读全文 »

坚持能力有大小与贡献须尽力相统一。 坚持物质贡献与精神贡献相统一。 坚持完善自身与贡献社会相统一。 坚持动机和效果相统一。

0%