背景:
线程采用抢占式调度,而C++光纤采用协同调度.使用P螺纹:当前执行路径可能在任何时候被中断或抢占--这意味着对于线程来说,数据完整性是一个大问题,因为一个线程可能会在更新数据块的过程中停止,从而使数据的完整性处于糟糕或不完整的状态。这也意味着操作系统可以利用多个CPU和CPU核心,同时运行多个线程,由开发人员来保护数据访问。使用C,int pthread_create(pthread_t *线程,const pthread_attr_t *attr,void *(*start_routine) (void *),void *arg);使用线程,应用程序可能具有并发性,并发属性: 1)多个参与者2)共享资源3)访问规则(原子/条件同步)
对于C++光纤:只有当光纤产生执行时,当前的执行路径才会被中断--这意味着光纤总是在定义良好的地方开始和停止,因此数据完整性问题要少得多。另外,由于光纤通常是在用户空间中管理的,因此不需要进行昂贵的上下文切换和CPU状态更改,从而使从一种光纤到另一种光纤的转换非常高效。另一方面,由于没有两个光纤能够同时运行,仅使用光纤并不能利用多个CPU或多CPU核心。在Win32中,光纤是一种用户管理的线程.一个光纤有它自己的堆栈和自己的指令指针等等,但是操作系统没有对光纤进行调度:您必须显式地调用SwitchToFiber。相反,线程是由操作系统预先安排的.因此,粗略地说,光纤是在应用程序/runti me级别管理的线程,而不是真正的OS线程。使用C,void __stdcall MyScheduler(void *param){ .} LPVOID *FiberScheduler = CreateFiber(0,MyScheduler,NULL);
为什么是C++纤维?OS线程为我们提供了我们想要的一切,但这是一个沉重的性能损失:线程之间的切换需要从用户跳到内核模式,甚至可能跨越地址空间边界。这些操作代价高昂,部分原因在于它们会导致TLB刷新、缓存丢失和CPU流水线破坏:这也是为什么陷阱和syscalls比常规过程调用慢几个数量级的原因。此外,内核使用通用调度算法调度线程(即将它们的延续分配给CPU核心),该算法可能会考虑所有类型的线程,从服务单个事务的线程到播放整个视频的线程。光纤,因为它们被安排在应用层,可以使用更适合其用例的调度程序。由于大多数光纤用于服务事务,它们通常在很短的时间内处于活动状态,并且经常被阻塞。它们的行为通常由IO或另一个光纤唤醒,运行一个短的处理周期,然后将控制转移到另一个光纤(使用队列或另一种同步机制),.Such行为最好由调度程序提供服务,该调度程序使用一种称为“偷工作”的算法;当光纤以这种方式运行时,偷工作确保了在光纤之间切换时丢失的缓存最小。
光纤没有利用多核的能力,因为操作系统知道的是单线程进程。
在GO中,我们使用go
关键字调用goroutines
func main(){
go f() // f runs as new go routine
f()
}
问题:
1) GO例程(f
)是GO运行时在用户空间中非先发制人地调度的光纤吗?
2)如果是,围棋环境中是否会出现并发情况?
3)支持操作系统级线程的api吗?
发布于 2017-01-31 12:19:42
问题1:不完全是
戈鲁丁有点奇怪。它们有点类似于纤维,但也有点类似于线程。
默认情况下,golang运行时通常会启动到GOMAXPROCS
线程,并将您的goroutines安排在其中。在任何给定的线程上,goroutine都会运行到完成或阻塞在通道上。
这意味着,您可以将goroutines看作线程间共享的纤维。
这意味着你可以想到那些不像你想象的那样进入全球状态的猩猩。但是对于访问全局状态的goroutines来说,您需要像线程一样对待它们。
问题2:是
在访问全局状态时,您需要注意!
然而,默认的通信机制,通道,同步访问共享资源,这大大简化了并发编程的围棋。
问题3:不在标准库中
如果你真的愿意,你可以用C语言编写一个库来启动线程,这样你就可以访问底层的OS线程函数(比如pthread_create
)。
但是,我强烈怀疑您能否在以这种方式创建的线程上使用goroutines和通道,因为golang运行时调度程序不知道它们。
这也可能导致调用其他库(如标准库!)的问题!假设他们可以进入峡谷和通道。
总之,我不认为在Go中直接创建和管理线程是个好主意。
发布于 2017-01-31 06:40:30
Goroutines是一个编译器工具。从概念上讲,Goroutines和纤维是与环境有关的协同多任务处理方法。光纤是OS级别的概念,而goroutine是编译器级的概念。
Goroutines可能与纤维规范相匹配(似乎有很多),但不一定是最严格意义上的纤维。事实上,根据调度程序的决定,大猩猩可以分布在多个线程上。
通信顺序进程(CSP)是go的并发模型,Goroutines实现了这一点。隔离戈鲁蒂部分并考虑并发性,这与金牙的观点有点不同。
我们鼓励您使用通道来维护数据流,而不依赖任何其他同步机制(正如pike所说,不要通过共享进行通信,通过通信来共享)。虽然您仍然可以使用互斥,但您仍然不能自己创建线程。
事实上,go的并发方法比其他传统语言及其实现更接近erlang。
Go使用与环境变量GOMAXPROCS设置的相同数量的OS线程( GO1.5设置为CPU核心计数)。
https://softwareengineering.stackexchange.com/questions/341262
复制相似问题