php是最好的语言

golang 并发demo

package utils

import (
   "sync"
)
type GoLimit struct {
   max       uint             //并发最大数量
   count     uint             //当前已有并发数
   isAddLock bool             //是否已锁定增加
   zeroChan  chan interface{} //为0时广播
   addLock   sync.Mutex       //(增加并发数的)锁
   dataLock  sync.Mutex       //(修改数据的)锁
}

func NewGoLimit(max uint) *GoLimit {
   return &GoLimit{max: max, count: 0, isAddLock: false, zeroChan: nil}
}


//并发计数加1.若 计数>=max_num, 则阻塞,直到 计数<max_num
func (g *GoLimit) Add() {
   g.addLock.Lock()
   g.dataLock.Lock()
   g.count += 1
   if g.count < g.max { //未超并发时解锁,后续可以继续增加
      g.addLock.Unlock()
   } else { //已到最大并发数, 不解锁并标记. 等数量减少后解锁
      g.isAddLock = true
   }
   g.dataLock.Unlock()
}


//并发计数减1
//若计数<max_num, 可以使原阻塞的Add()快速解除阻塞
func (g *GoLimit) Done() {
   g.dataLock.Lock()
   g.count -= 1
   //解锁
   if g.isAddLock == true && g.count < g.max {
      g.isAddLock = false
      g.addLock.Unlock()
   }
   //0广播
   if g.count == 0 && g.zeroChan != nil {
      close(g.zeroChan)
      g.zeroChan = nil
   }
   g.dataLock.Unlock()
}
//更新最大并发计数为, 若是调大, 可以使原阻塞的Add()快速解除阻塞
func (g *GoLimit) SetMax(n uint) {
   g.dataLock.Lock()
   g.max = n
   //解锁
   if g.isAddLock == true && g.count < g.max {
      g.isAddLock = false
      g.addLock.Unlock()
   }
   //加锁
   if g.isAddLock == false && g.count >= g.max {
      g.isAddLock = true
      g.addLock.Lock()
   }
   g.dataLock.Unlock()
}
//若当前并发计数为0, 则快速返回; 否则阻塞等待,直到并发计数为0
func (g *GoLimit) WaitZero() {
   g.dataLock.Lock()
   //无需等待
   if g.count == 0 {
      g.dataLock.Unlock()
      return
   }
   //无广播通道, 创建一个
   if g.zeroChan == nil {
      g.zeroChan = make(chan interface{})
   }
   //复制通道后解锁, 避免从nil读数据
   c := g.zeroChan
   g.dataLock.Unlock()
   <-c
}
//获取并发计数
func (g *GoLimit) Count() uint {
   return g.count
}
//获取最大并发计数
func (g *GoLimit) Max() uint {
   return g.max
}


调用:

g := utils.NewGoLimit(10) //max_num(最大允许并发数)设置为10
for k, v := range filePaths {
   g.Add()

   go func(g *utils.GoLimit,k int,v string) {
      defer g.Done() //并发计数减1
      p.PostFile(v, url, map[string]string{"guid": guid, "chunk": cast.ToString(k)})
   }(g,k,v)


}

g.WaitZero() //阻塞, 直到所有并发都完成


作者:xTao 分类:LNMP 浏览:2288 评论:0