nodejs和golang协程的不同

2024-05-09 19:08

1. nodejs和golang协程的不同

nodejs和golang都是支持协程的,从表现上来看,nodejs对于协程的支持在于async/await,golang对协程的支持在于goroutine。关于协程的话题,简单来说,可以看作是非抢占式的轻量级线程。

nodejs和golang协程的不同

2. golang 协程 使用什么标识

线程和C#的线程没区别,重点在于协程。 协程Coroutine并不是多线程的,只是运转的结果很像多线程而已。 MonoBehavior的每个周期里都会检查一次是否需要执行协程,如果需要,就执行。所以是Unity的主线程调用了协程里的代码,你要是写个死循环的

3. 最近在看golang 的 协程,一直很疑问如何开启多个协程

线程和C#的线程没区别,重点在于协程。 协程Coroutine并不是多线程的,

最近在看golang 的 协程,一直很疑问如何开启多个协程

4. 协程与函数线程异步的关系

什么协程
协程这个概念在计算机科学里算是一个老概念了,随着现代计算机语言与多核心处理器的普及,似乎也有普及之势。协程是与例程相对而言的。
熟悉C/C++语言的人都知道,一个例程也就是一个函数。当我们调用一个函数时,执行流程进入函数;当函数执行完成后,执行流程返回给上层函数或例程。期间,每个函数执行共享一个线程栈;函数返回后栈顶的内容自动回收。这就是例程的特点,也是现代操作系统都支持这种例程方式。
协程与例程相对,从抽象的角度来说,例程只能进入一次并返回一次,而协程可能进入多次并返回多次。比如说,我们有下面一段程序:

void fun(int val)
{
int a=0; //1

int b=0; //2

int c=a+b; //3
}
如果上面的代码是一个例程,那么它只能把 1、2、3 依次执行后,才返回。如果是协程,它可能在 1 处暂停,然后在某个时刻从 2 处继续执行;接着在 2 处执行完之后暂停,然后在另外一个时刻从 3 处继续执行。
从抽象角度,协程就这么简单。
异步IO的特点与分析
在了解协程的特点(可以多次进入同一个函数,并接着上次运行处继续执行)后,我们再来考虑一下,这一特点如何应用到异步IO程序中。在异步IO程序中,有很大一块代码是处理异步回调的,也就是数据读取或写入由系统执行,当任务完成后,系统会执行用户的回调。如果只是很少使用这种回调,那么程序并不会因为异步而复杂多少,但要是程序中异步回调大量存在,那么此时我们会发现,原本简单的程序可能因为回调而变得支离破碎,原本一个简单的循环,现在需要写入多个函数,并在多个函数里来回调用。下面示例一下:

//下面代码片断是同步代码,它从IO读一段数据,并把这段数据写回
void start()
{
for(;;)
{
Buffer buf;
read (buf);//把书读到buf
write(buf);//把buf的数据写回
}

//注意到没有,同步代码很简单直接,一个循环,几行代码完成全部事务
}

//把上面的同步代码映射为异步,代码量可能要增加很多,并且程序逻辑也变得不清晰
//示例如下

//读回调,在回调里我们发起写操作
void readHandle(buf)
{
writeAsync(buf, writeHandle);
}

//写回调,在回调里我们发起读操作
void writeHandle(buf)
{
readAsync(buf, readHandle);
}

//开始循环
void start()
{
static Buffer buf; //buf变量不能在栈上,为了简单这里写成静态变量
readAsync(buf, readHandle);
}
从上面的代码比较中,我们可以看出异步IO会把代码分隔成许多碎片,同时原本清晰的处理逻辑也因为被放入多个函数里,而变得很不清晰。上面的同步代码,一个了解程序的初级程序员也可以读懂写出,但相同功能的异步代码,一个初级程序员可能就搞不定了,甚至很难搞明白为什么要这么做。
读到这里,对异步不是太了解的人可能会问,既然异步把问题搞复杂了,那我们为什么还要用异步呢?答案简单有力,为了“性能”。只有这一个原因,当程序需要处理大量IO时,异步的效率将高出同步代码许多倍。如何一个程序的性能不其关心部分,那真不应该使用异步IO。
对比我们的异步IO代码与其功能相同的同步代码,我们发现每个异步调用都是要把代码分隔一个小函数——比原本要小的函数,当异步调用返回后,我们又接着下面处理。这一点跟协程很像,在一个协程里,当发起异步IO时,我让它返回,当异步IO完成后,我让这个协程接着执行,处理余下的逻辑。
协程与异步结合——性能与简单的结合
结合上面的分析,如果我们可以写下面功能的代码,将很完美:

void start()
{
for(;;)
{
Buffer buf;

yeild readAsync(buf,start);
//------ 分隔线,协程在这里返回,等待readAsync完成,当readAsync完成后,它再调用start
//此时start将从这里接着运行

yeild writeAsync(buf, start);
//------ 分隔线,协程在这里返回,等待writeAsync完成,当writeAsync完成后,它再调用start
//此时start将从这里接着运行
}
}
上面的代码也很一清晰明了。如果真的能写这样的代码,那将是所有程序员之福。这样在一些语言里确实可以直接写出来,比如Python、Lua、 golang,这些语言有原生的协程支持——编译器或解释器为我们处理了这些执行流的跳转。那么在C/C++里怎么实现呢?可能肯定的是,C/C++里不能直接写出这样简洁的代码,但却可以写类似的代码,尤其是C++——它提供了更强大的封装能力。

5. golang开发的tcp服务多个task时怎么设计协程和chan

线程和C#的线程没区别,重点在于协程。 协程Coroutine并不是多线程的,

golang开发的tcp服务多个task时怎么设计协程和chan

6. golang协程占用资源小,有必要写协程池吗

和你有同样的疑问。 我在google上搜索关于这方面的文章不多。目前的处理方式还是普遍通过channel接收,有任务进来才开启协程,不会一直保留,顶多设置一个协程开启上限。

7. golang web 浏览器每请求一次 golang是启动一个新的线程吗

是协程,每一个请求都会单独启动一个 goroutine,可以理解为轻量级线程

golang web 浏览器每请求一次 golang是启动一个新的线程吗

8. golang channel 是线程安全的么

如果把线程安全定义为允许多个goroutine同时去读写,那么golang 的channel 是线程安全的。不需要在并发读写同一个channe时加锁。