加入收藏 | 设为首页 | 会员中心 | 我要投稿 南京站长网 (https://www.025zz.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

PHP混合Go协程并发

发布时间:2016-11-04 23:09:35 所属栏目:PHP教程 来源:segmentfault
导读:副标题#e# 想法很简单。通过设置 runtime.GOMAXPROCS(1) 让 golang 的进程变成单线程执行的。类似python用gevent的效果。然后通过调度多个协程实现异步I/O并发。php作为一个子函数跑在go的进程内,php需要yield到其他协程时,通过回调到golang函数来实现。
副标题[/!--empirenews.page--]

PHP混合Go协程并发

想法很简单。通过设置 runtime.GOMAXPROCS(1) 让 golang 的进程变成单线程执行的。类似python用gevent的效果。然后通过调度多个协程实现异步I/O并发。php作为一个子函数跑在go的进程内,php需要yield到其他协程时,通过回调到golang函数来实现。从php里调用go提供的子函数时,go保证保存php的当前上下文。当协程执行权让渡回来的时候,把原来的php上下文恢复。关键的代码在:

  1.  // 保存当前协程上的php上下文    
  2. oldServerCtx := engine.ServerContextGet() 
  3.     fmt.Println(oldServerCtx) 
  4.     defer engine.ServerContextSet(oldServerCtx) 
  5.     oldExecutorCtx := engine.ExecutorContextGet() 
  6.     fmt.Println(oldExecutorCtx) 
  7.     defer engine.ExecutorContextSet(oldExecutorCtx) 
  8.     oldCoreCtx := engine.CoreContextGet() 
  9.     fmt.Println(oldCoreCtx) 
  10.     defer engine.CoreContextSet(oldCoreCtx) 
  11.  
  12. // 放弃全局的锁,使得其他的协程可以开始执行php 
  13.     engineLock.Unlock() 
  14.     defer engineLock.Lock()  

ServerContextGet 这几个函数是我加的,获得的是php的(EG/SG/PG)这三个全局context(参见:http://www.cnblogs.com/chance...)。修改过的github.com/deuill/go-php的源代码在:https://github.com/taowen/go-...

完整的php/go混合协程的demo:

  1. package main 
  2.  
  3. import ( 
  4.     "fmt" 
  5.     "github.com/deuill/go-php/engine" 
  6.     "os" 
  7.     "runtime" 
  8.     "time" 
  9.     "sync" 
  10. ) 
  11.  
  12. type TestObj struct{} 
  13.  
  14. func newTestObj(args []interface{}) interface{} { 
  15.     return &TestObj{} 
  16. } 
  17. var engineLock *sync.Mutex 
  18.  
  19. func (self *TestObj) Hello() { 
  20.     oldServerCtx := engine.ServerContextGet() 
  21.     fmt.Println(oldServerCtx) 
  22.     defer engine.ServerContextSet(oldServerCtx) 
  23.     oldExecutorCtx := engine.ExecutorContextGet() 
  24.     fmt.Println(oldExecutorCtx) 
  25.     defer engine.ExecutorContextSet(oldExecutorCtx) 
  26.     oldCoreCtx := engine.CoreContextGet() 
  27.     fmt.Println(oldCoreCtx) 
  28.     defer engine.CoreContextSet(oldCoreCtx) 
  29.     engineLock.Unlock() 
  30.     defer engineLock.Lock() 
  31.     time.Sleep(time.Second) 
  32.     fmt.Println("sleep done") 
  33. } 
  34.  
  35. func main() { 
  36.     runtime.GOMAXPROCS(1) 
  37.     theEngine, err := engine.New() 
  38.     engineLock = &sync.Mutex{} 
  39.     if err != nil { 
  40.         fmt.Println(err) 
  41.     } 
  42.     _, err = theEngine.Define("TestObj", newTestObj) 
  43.     wg := &sync.WaitGroup{} 
  44.     wg.Add(2) 
  45.     before := time.Now() 
  46.     fmt.Println("1") 
  47.     go func() { 
  48.         engineLock.Lock() 
  49.         defer engineLock.Unlock() 
  50.         context1, err := theEngine.NewContext() 
  51.         if err != nil { 
  52.             fmt.Println(err) 
  53.         } 
  54.         context1.Output = os.Stdout 
  55.         if err != nil { 
  56.             fmt.Println(err) 
  57.         } 
  58.         fmt.Println("1 enter") 
  59.         _, err = context1.Eval("$testObj = new TestObj(); $testObj->Hello();") 
  60.         fmt.Println("1 back") 
  61.         if err != nil { 
  62.             fmt.Println(err) 
  63.         } 
  64.         //theEngine.DestroyContext(context1) 
  65.         fmt.Println("1 done") 
  66.         wg.Done() 
  67.     }() 
  68.     fmt.Println("2") 
  69.     go func() { 
  70.         engineLock.Lock() 
  71.         defer engineLock.Unlock() 
  72.         context2, err := theEngine.NewContext() 
  73.         if err != nil { 
  74.             fmt.Println(err) 
  75.         } 
  76.         if err != nil { 
  77.             fmt.Println(err) 
  78.         } 
  79.         context2.Output = os.Stdout 
  80.         fmt.Println("2 enter") 
  81.         _, err = context2.Eval("$testObj = new TestObj(); $testObj->Hello();") 
  82.         fmt.Println("2 back") 
  83.         if err != nil { 
  84.             fmt.Println(err) 
  85.         } 
  86.         //theEngine.DestroyContext(context2) 
  87.         fmt.Println("2 done") 
  88.         wg.Done() 
  89.     }() 
  90.     wg.Wait() 
  91.     after := time.Now() 
  92.     fmt.Println(after.Sub(before)) 
  93. }  

(编辑:南京站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读