在并发编程中,对共享资源的并发访问会导致各种问题,如数据竞赛。为了消除意外行为,对共享资源的并发访问必须受到保护。这个被保护的部分被称为关键部分。关键部分绝不能被一个以上的进程同时执行。
在这个例子中,我们要确保一个银行账户状态的完整性不被破坏。我们将通过使用两种通用的同步机制来实现这一点,这两种机制是semaphore和mutex。这两种机制都是用来保护关键部分的。它们实现了互斥,限制了对多种资源的访问,解决了读者和写者的问题,等等。
-
**突变器。**Mutex通过允许单个线程独占访问(相互排斥)来保护关键部分。
-
**傀儡(Semaphore)。**semaphore(一个变量或一个抽象数据类型)通过允许N个线程独占访问(互斥)来保护一个关键部分。
鉴于信号灯可以允许对共享资源进行多次访问,我们将把它限制为1。这被称为二进制信号灯,与使用容量为1的缓冲通道的情况相同。
银行骨架
这是我们的银行账户的基本框架。当我们使用不同的例子时,我们会更新它。
package bank
这是我们用来运行测试的主要代码,它将保持原样。
package main
一次一个读和一个写
确保每次只有一个goroutine访问资金。每个goroutine都有对资金的独占访问权,所以如果一个正在读取,另一个就会等待,反之亦然。这被认为是一个线程安全操作。
选项1:二进制信号/缓冲通道
我们在这里没有直接实现信号灯,但是如果你想创建和使用信号灯包,请看底部的例子。
package bank
- Bal 0 @ 2020-04-13 14:01:33.650511 +0000 UTC
选项2:同步.Mutex
package bank
- Bal 0 @ 2020-04-13 13:47:32.016951 +0000 UTC
每次有许多读和一个写
允许许多goroutines在同一时间访问资金(一个共享的变量/资源)。然而,只有一个人可以写入,当这种情况发生时,读取也被阻断。如果没有人在写,则允许许多读,因为它被认为是一个有条件的安全操作。同样,只要没有人同时在写!这对高读流量的情况是很好的。
package bank
- Bal 0 @ 2020-04-13 13:53:44.060959 +0000 UTC
拴马桩包
这就是一个信号包的样子。
package semaphore
使用方法
如果你愿意,你可以把它和我们的银行例子一起使用,如下所示。
package bank
package bank
如果你想单独使用这个包的话,这里有一个简单的例子。在这种情况下,资源槽被灵活地使用,而不是像我们上面的银行例子那样只有一个槽。
package main