并去发编程之互斥是什么

  介绍

这篇文章给大家分享的是有关并去发编程之互斥是什么的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。

我们比较常见的大型项目的设计中都会出现并发访问问题,并发就是为了解决数据的准确性,保证同一个临界区的数据只能被一个线程进行操作,日常中使用到的并发场景也是很多的:

    <李> <强>计数器:计数器结果不准确,李 <李> <强>秒杀系统:由于同一时间访问量比较大,导致的超卖; <李> <强>用户账户异常:同一时间支付导致的账户透支; <李> <强>缓冲区数据异常:更新缓冲区导致的数据混乱。

上面都是并发带来的数据准确性的问题,决绝方案就是使用<>强互斥锁强,也就是今天并发编程中的所要描述的互斥锁并发原语。

实现机制

互斥锁互斥就是为了避免并发竞争建立的并发控制机制,其中有个“临界区”的概念。

在并发编程过程中,如果程序中一部分资源或者变量会被并发访问或者修改,为了避免并发访问导致数据的不准确,这部分程序需要率先被保护起来,之后操作,操作结束后去除保护,这部分被保护的程序就叫做<强>临界区

<强>使用互斥锁,限定临界区只能同时由一个线程持有强,若是临界区此时被一个线程持有,那么其他线程想进入到这个临界区的时候,就会失败或者等待释放锁,持有此临界区的线程退出,其他线程才有机会获得这个临界区。

叭ゲ⒎⒈喑讨コ馐鞘裁?

去互斥临界区示意图

互斥是去语言中使用最广泛的同步原语,也称为并发原语,<强>解决的是并发读写共享资源,避免出现数据竞争数据竞赛问题

基本使用

<>强互斥锁互斥提供了两个方法和锁解锁:进入到临界区使用锁方法加锁,退出临界区使用解锁方法释放锁。

类型储物柜接口{   Lock ()   解锁()}func (m *互斥)锁()函数(m *互斥)解锁()

<强>当一个goroutine调用锁方法获取到锁后,其他goroutine会阻塞在锁的调用上,直到当前获取到锁的goroutine释放锁。

接下来是一个计数器的例子,是由100个goroutine对计数器进行累加操作,最后输出结果:

包mainimport (   “fmt"   “sync")函数main () {   varμsync.Mutex   countNum:=0//确认辅助变量是否都执行完成   var wg同步。WaitGroup//wg添加数目要和创建的协程数量保持一致   wg.Add (100)   我:=0;我& lt;100;我+ + {   去func () {   推迟wg.Done ()   j:=0;j & lt;1000;j + + {   mu.Lock ()   countNum + +   mu.Unlock ()   }   }()   }   wg.Wait ()   fmt.Printf (“countNum: % d" countNum)}

实际使用

很多时候互斥锁并不是单独使用的,而是嵌套在结构体中使用,作为结构体的一部分,<强>如果嵌入的结构有多个字段,我们一般会把互斥放在要控制的字段上面,然后使用空格把字段分隔开来。

<强>甚至可以把获取锁,释放锁,计数加一的逻辑封装成一个方法。

包mainimport (   “fmt"   “sync")//线程安全的计数器类型计数器结构{   相等物int   名称字符串      μsync.Mutex   计数uint64}//加一方法func (c *柜台)增加(){   c.mu.Lock ()   推迟c.mu.Unlock ()   c。数+ +}//取数值方法线程也需要受保护func (c *柜台)数()uint64 {   c.mu.Lock ()   推迟c.mu.Unlock ()   返回c。数}函数main () {//定义一个计数器   var柜台柜台var wg sync.WaitGroup   wg.Add (100)      我:=0;我& lt;100;我+ + {   去func () {   推迟wg.Done ()   j:=0;j & lt;1000;j + + {   counter.Incr ()   }   }()   }   wg.Wait ()      fmt.Printf (“% d \ n" counter.Count ())}

感谢各位的阅读!关于去并发编程之互斥是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到吧!

并去发编程之互斥是什么