并发与线程
并发与线程
async
vino提供了非常简单的多线程编程api,在函数调用前添加async
关键字,即可让函数在一个新的线程中执行。
示例
//创建函数
function a() {
console.log("hello vino");
}
//执行函数,这个操作会在一个新的线程中来执行a函数。
async a();
提示
- 这个示例代码并不会打印"helle vino",因为主线程已经结束,所以子线程不会被执行。
- vino中
async
和JavaScript中的async
是完全不同的,因为vino是基于多线程的运行时,所以并不需要在函数声明时指定函数为异步函数,而是在函数执行时进行异步或同步执行。
sync
vino
在多线程执行时,会带来线程同步的问题,这个问题在JavaScript
中并不存在,因为它只有1个线程。vino
提供了一个函数锁功能,可以给函数添加线程同步锁,当多个线程同时执行某一个函数时确保只有1个线程可以调用该函数。
在函数的执行前添加关键字sync
来进行加锁。
function a(){
//一些代码
}
sync a()
- 示例
let a = 0;
let b = 0;
function aCounter() {
a++;
}
function bCounter() {
b++;
}
function aExec() {
//线程同步执行aCounter函数
sync aCounter();
}
function bExec() {
//异步执行
bCounter();
}
for (let i = 0; i < 1000; i++) {
//开启1000个线程来异步执行
async aExec();
async bExec();
}
sleep(1000);
//a的结果是1000
console.log(a);
//b的结果小于1000的随机数
console.log(b);
线程池
提示
vino还提供了ThreadPool线程池类,可以实现更多线程控制
关于多线程
vino
中线程的实现并不是真正的线程,而是协程,为了便于初学者学习和理解,所以文档中对于并发的描述都是线程。
协程是实现并发编程的一种轻量级线程,由运行时管理。它们相对于传统的操作系统线程有许多优势。
原理
轻量级
协程是轻量级的,它们的创建和销毁开销非常低。每个协程只需很少的内存(大约几KB),这使得在同一时间内可以运行成千上万个协程,而不会消耗大量系统资源。
调度器
运行时包含一个内置的协程调度器,负责管理协程的调度。这个调度器是M模型的实现,即M个协程可以在N个操作系统线程上运行。调度器可以将协程在不同的操作系统线程之间进行切换,从而充分利用多核CPU的优势。
非阻塞IO
通过使用非阻塞IO操作,使得协程在等待IO操作完成时不会阻塞线程。这意味着一个线程可以在多个协程之间高效地切换,即使其中一些协程在等待IO操作。
抢占式调度
调度器采用抢占式调度机制,可以确保协程不会因为某个协程长时间占用CPU而导致其他协程无法执行。调度器会在适当的时候将CPU从一个协程转移到另一个协程。
优势
高并发
由于协程的轻量级特性,vino
程序可以在同一时间创建和管理大量的协程,从而实现高并发。这对于需要处理大量并发请求的服务器应用特别有用。
简化并发编程
vino
通过async
关键字轻松启动一个新的协程。
性能优化
运行时的调度器可以高效地利用系统资源,确保协程能够在多个CPU核心上并行执行,从而提高程序的性能。此外,协程的非阻塞IO特性使得程序可以高效地处理大量IO密集型任务。
内存占用低
与操作系统线程相比,协程的内存占用非常低。这意味着在同样的系统资源下,vino
程序可以运行更多的并发任务。