设为首页 收藏本站
查看: 1255|回复: 0

[经验分享] PCWen's blog

[复制链接]

尚未签到

发表于 2018-9-20 11:17:50 | 显示全部楼层 |阅读模式
  Go1.9.2 sync库里包含下面几类:Mutex/RWMutex/Cond/WaitGroup/Once/Map/Pool
  1.Mutex:互斥锁,等同于linux下的pthread_mutex_t
  

//多个线程同时运行,获得Mutex锁者线程优先执行,其余线程阻塞等待  
func testMutex() {
  
mutex :
= sync.Mutex{};  

for i := 0; i < 10; i++ {  
go func(idx
int) {  
mutex.Lock();
  
defer mutex.Unlock();
  
fmt.Println(
"idx :=",>
time.Sleep(time.Second);  
}(i)
  
}
  

  
time.Sleep(
20 * time.Second);  
fmt.Println(
"Func finish.");  
}
  

  2.RWMutex:读写锁,等同于linux下的pthread_rwlock_t
  

//写请求在读锁和写锁时都必须阻塞等待,读请求只在写锁时阻塞等待  
func testRWMutex() {
  
rwMutex :
= sync.RWMutex{};  

for i := 0; i < 10; i++ {  
go func(idx
int) {  
rwMutex.RLock();
  
defer rwMutex.RUnlock();
  
fmt.Println(
"Read Mutex :",idx);  
}(i);
  

  
go func(idx
int) {  
rwMutex.Lock();
  
defer rwMutex.Unlock();
  
fmt.Println(
"Write Mutex :",idx);  
time.Sleep(time.Second);
  
}(i);
  
}
  

  
time.Sleep(
20 * time.Second);  
fmt.Println(
"Func finish.");  
}
  

  3.Cond:条件变量,等同于linux下的pthread_cond_t
  

func testCond() {  
cond :
= sync.NewCond(&sync.Mutex{});  

  
cond.L.Lock();
//①上锁  
    defer cond.L.Unlock();
  

  
go func() {
  
fmt.Println(
"go wait lock.");  
cond.L.Lock();
//②等Wait解锁  

  
defer cond.L.Unlock(); //⑤解锁后触发Wait
  
defer fmt.Println("go unlock.");
  

  
fmt.Println("go locked.");
  
cond.Signal(); //④触发Wait等待解锁
  
    }()
  

  
time.Sleep(time.Second);
  

  
fmt.Println("start wait.");
  
for {
  
cond.Wait(); //③可以理解为立刻解锁并触发一个阻塞线程(如果没有阻塞线程则不触发)后立刻再上锁等待Signal信号
  
fmt.Println("wait finish.");
  
break;
  
}
  

  
time.Sleep(time.Second);
  
fmt.Println("Func finish.");
  
}
  

  4.WaitGroup:组等待
  

//Add 增加等待计数;Done减少等待计数;当计数为0时触发Wait;  
func testWaitGroup() {
  
waitGroup :
= sync.WaitGroup{};  

for i := 0; i < 10; i++ {  
waitGroup.Add(
1);  

  
go func(idx
int) {  
time.Sleep(time.Second);
  
fmt.Println(
"go : ",>
waitGroup.Done();  
}(i)
  
}
  

  

for{  
fmt.Println(
"start wait.");  
waitGroup.Wait();
  
fmt.Println(
"wait finish.");  

break;  
}
  

  
time.Sleep(time.Second);
  
fmt.Println(
"Func finish.");  
}
  

  5.Once:只执行一次
  

//只执行一次以后不再触发  
func testOnce() {
  
once :
= sync.Once{};  

for i := 0; i < 10; i++ {  
go func(idx
int) {  
once.Do(func() {
  
fmt.Println(
"Do once : ",>
            })  

  
fmt.Println("go : ",>  
}(i)
  
}
  

  
time.Sleep(5 * time.Second);
  
fmt.Println("Func finish.");
  
}
  

  6.Map:线程安全map
  

func testMap() {  
syncMap :
= sync.Map{};  

for i := 0; i < 10; i++ {  
go func(idx
int) {  

//如果没有则保存起来  
_, ok := syncMap.LoadOrStore(idx, " StrVal = "+strconv.FormatInt(int64(idx), 10));
  

if !ok {  
fmt.Println(
"Store>
}
  
}(i)
  

  
go func(idx
int) {  
val, ok :
= syncMap.Load(idx);  

if ok {  
fmt.Println(
"Load success>
}else {  
fmt.Println(
"Load fail>
}  
}(i)
  

  
}
  

  
time.Sleep(
5 * time.Second);  
fmt.Println(
"Func finish.");  
}
  

  7.Pool:线程安全对象池
  

func testPool() {  
p :
= &sync.Pool{  
New: func()
interface{} {  

return -1;  
},
  
}
  

  

for i := 0; i < 10; i++ {  
go func(idx
int) {  
p.Put(idx);
  
}(i)
  
}
  

  

//取出来的对象是无序的  
for i := 0; i < 20; i++ {
  
go func() {
  
val :
= p.Get();  
fmt.Println(
"Get val = ", val);  
}()
  
}
  

  
time.Sleep(
5 * time.Second);  
fmt.Println(
"Func finish.");  
}
  

  使用Pool一定要注意一下问题:
  1.用途仅仅是增加对象重用的几率,减少gc的负担,而开销方面也不是很便宜的。
  2.GC会将Pool清理掉。
  3.Get不能保证将Put进去的全部取出来!如下例子:
  

func testPoolPutGet(){  
myPool :
= &sync.Pool{  
New: func()
interface{} {  

return 0;  
},
  
}
  

  
myPool.Put(
1) //放入1  
myPool.Put(2) //放入2
  

  
time.Sleep(time.Second)
  

  
p1 :
= myPool.Get().(int)  
fmt.Println(p1)
// 获得2  

  
p2 := myPool.Get().(int)
  
fmt.Println(p2) // 获得0,而不是1!
  
}
  

  4.关于Pool的实现原理,可以参考《go语言的官方包sync.Pool的实现原理和适用场景》
  以上。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-598797-1-1.html 上篇帖子: Golang 模板 下篇帖子: golang type
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表