Semaphores
- Dijkstra (1965) introduced the concept of a semaphore
- A semaphore is an integer variable that is accessed through two standard atomic operations: wait ( a spinlock, i.e. stops blocking and decrements thesemaphore) and signal (i.e. the semaphore counts the signals it receives)
- Semaphores are variables that are used to signal the status of shared resources to processes (a semaphore could have the value of 0, indicating that no wakeups are saved, or some positive value if one or more wakeups are pending)
- How does that work?
- If a resource is not available, the corresponding semaphore blocks any process waiting for the resource
- Blocked processes are put into a process queue maintained by the semaphore (avoids busy waiting!)
- When a process releases a resource, it signals this by means of the semaphore
- Signalling resumes a blocked process if there is any
- Wait and signal operations cannot be interrupted
- Complex coordination can be specified by multiple semaphores
- the down operation on a semaphore
- checks to see if the value is greater than 0
- if so, it decrements the value and continues
- if the value is 0, the process is put to sleep without the completing the down for the moment
- all is done as a single, indivisible atomic action
- checking the value
- changing it
- possibly going to sleep
- it is guaranteed that once a semaphore operation has started, no other process can access the semaphore until the operation has completed
- synchronization and no race condition
- the up operation on a semaphore
- increments the value of the semaphore
- if one or more processes were sleeping on that semaphore, unable to complete an earlier down operation, one of them is chosen by the system and allowed to complete its down
- the semaphore will be 0. but there will be one fewer process sleeping on it
- indivisible process; incrementing the semaphore and waking up one process
- Solving the producer-consumer problem using semaphores (see Fig. 2.14)
- the solution uses three semaphores;
- one called full for counting the number of slots that are full
- one called empty for counting the number of slots that are empty
- one called mutex to make sure the producer and the consumer do not access the buffer at the same time. mutex is initially 1 (binary semaphore)
- if each process does a down just before entering its CR and an up just after leaving it, the mutual exclusion is guaranteed.
- Possible uses of semaphores;
- Mutual exclusion, initialize the semaphore to one
- Synchronization of cooperating processes (signaling), initialize the semaphore to zero
- Managing multiple instances of a resource, initialize the semaphore to the number of instances
- Type of semaphores;
- binary is a semaphore with an integer value of 0 and 1.
- counting is a semaphore with an integer value ranging between 0 and an arbitrarily large number. Its initial value might represent the number of units of the critical resources that are available. This form is also known as a general semaphore.
const N = 1
var mutex int64 = 1
var empty int64 = N
var full int64 = 0
func Producer() {
var item int
for {
item = producer_item()
down(&empty, "Producer empty")
down(&mutex, "Producer mutex")
insert_item(item)
up(&mutex, "Producer mutex")
up(&full, "Producer full")
}
}
func Consumer() {
var item int
for {
down(&full, "Consumer full")
down(&mutex, "Consumer mutex")
item = item_remove_item()
testRace(item, 2)
up(&mutex, "Consumer mutex")
up(&empty, "Consumer empty")
consumer_item(item)
}
}
package semaphore
import (
"container/list"
"sync/atomic"
"time"
)
const N = 1
var mutex int64 = 1
var empty int64 = N
var full int64 = 0
var testMap = map[int]int{}
func Producer() {
var item int
for {
item = producer_item()
down(&empty, "Producer empty")
//down(&mutex, "Producer mutex")
insert_item(item)
testRace(item, 1)
//up(&mutex, "Producer mutex")
up(&full, "Producer full")
}
}
func testRace(item int, value int) {
testMap[item] = value
}
func Consumer() {
var item int
for {
down(&full, "Consumer full")
//down(&mutex, "Consumer mutex")
item = item_remove_item()
testRace(item, 2)
//up(&mutex, "Consumer mutex")
up(&empty, "Consumer empty")
consumer_item(item)
}
}
var items list.List
var i = 0
func producer_item() int {
i++
println("producer_item item:", i)
return i
}
func consumer_item(item int) {
println("consumer_item item:", item)
}
func insert_item(item int) {
items.PushBack(item)
println("insert_item:", item)
}
func item_remove_item() int {
length := items.Len()
front := items.Front()
items.Remove(front)
tmp := front.Value.(int)
println("item_remove_item:", tmp, "length:", length)
return tmp
}
func down(v *int64, tag string) {
for *v <= 0 {
time.Sleep(1)
println("down: wait... *v <= 0 ,*v:", *v, "tag:", tag)
}
old := *v
t := atomic.AddInt64(v, -1)
println("down:", t, "old:", old, "tag:", tag)
}
func up(v *int64, tag string) {
old := *v
t := atomic.AddInt64(v, 1)
println("up:", t, "old:", old, "tag:", tag)
}
调用main
func main() {
go semaphore.Producer()
go semaphore.Consumer()
time.Sleep(30 * time.Millisecond)
println("main finished")
}
临界资源为1
所以运行没有问题:
结果如下:
。。。
insert_item: 348
up: 1 old: 0 tag: Producer full
producer_item item: 349
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: 0 old: 1 tag: Consumer full
item_remove_item: 348 length: 1
down: wait... *v <= 0 ,*v: 0 tag: Producer empty
down: 0 old: 1 tag: Producer empty
insert_item: 349
up: 1 old: 0 tag: Producer full
producer_item item: 350
up: 1 old: 0 tag: Consumer empty
consumer_item item: 348
down: 0 old: 1 tag: Consumer full
item_remove_item: 349 length: 1
up: 1 old: 0 tag: Consumer empty
consumer_item item: 349
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Producer empty
down: 0 old: 1 tag: Producer empty
insert_item: 350
up: 1 old: 0 tag: Producer full
producer_item item: 351
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: 0 old: 1 tag: Consumer full
item_remove_item: 350 length: 1
up: 1 old: 0 tag: Consumer empty
consumer_item item: 350
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Producer empty
down: 0 old: 1 tag: Producer empty
insert_item: 351
up: 1 old: 0 tag: Producer full
producer_item item: 352
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: 0 old: 1 tag: Consumer full
item_remove_item: 351 length: 1
up: 1 old: 0 tag: Consumer empty
consumer_item item: 351
down: wait... *v <= 0 ,*v: 0 tag: Producer empty
down: 0 old: 1 tag: Producer empty
insert_item: 352
up: 1 old: 0 tag: Producer full
producer_item item: 353
down: wait... *v <= 0 ,*v: 0 tag: Producer empty
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: 0 old: 1 tag: Consumer full
item_remove_item: 352 length: 1
up: 1 old: 0 tag: Consumer empty
consumer_item item: 352
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Producer empty
down: 0 old: 1 tag: Producer empty
insert_item: 353
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
up: 1 old: 0 tag: Producer full
producer_item item: 354
down: wait... *v <= 0 ,*v: 0 tag: Producer empty
down: wait... *v <= 0 ,*v: 0 tag: Producer empty
down: wait... *v <= 0 ,*v: 1 tag: Consumer full
down: 0 old: 1 tag: Consumer full
item_remove_item: 353 length: 1
up: 1 old: 0 tag: Consumer empty
consumer_item item: 353
down: wait... *v <= 0 ,*v: 0 tag: Producer empty
down: 0 old: 1 tag: Producer empty
insert_item: 354
up: 1 old: 0 tag: Producer full
producer_item item: 355
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: 0 old: 1 tag: Consumer full
item_remove_item: 354 length: 1
up: 1 old: 0 tag: Consumer empty
consumer_item item: 354
down: wait... *v <= 0 ,*v: 0 tag: Producer empty
down: 0 old: 1 tag: Producer empty
insert_item: 355
up: 1 old: 0 tag: Producer full
producer_item item: 356
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: 0 old: 1 tag: Consumer full
item_remove_item: 355 length: 1
up: 1 old: 0 tag: Consumer empty
consumer_item item: 355
down: wait... *v <= 0 ,*v: 0 tag: Producer empty
down: 0 old: 1 tag: Producer empty
insert_item: 356
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: 0 old: 1 tag: Consumer full
item_remove_item: 356 length: 1
up: 1 old: 0 tag: Consumer empty
consumer_item item: 356
up: 1 old: 0 tag: Producer full
producer_item item: 357
down: 0 old: 1 tag: Producer empty
main finished
insert_item: 357
up: 1 old: 0 tag: Producer full
producer_item item: 358
const N = 300
理论因为,empty信号量为300,生产和消费会并发修改。
报错如下:
down: 17 old: 18 tag: Consumer full
item_remove_item: 404 length: 18
up: 283 old: 282 tag: Consumer empty
consumer_item item: 404
up: 20 old: 19 tag: Producer full
producer_item item: 422
down: 282 old: 283 tag: Producer empty
down: 16 old: 17 tag: Consumer full
item_remove_item: 405 length: 18
up: 283 old: 282 tag: Consumer empty
consumer_item item: 405
down: 15 old: 16 tag: Consumer full
item_remove_item: 406 length: 17
insert_item: 422
fatal error: concurrent map writes
goroutine 5 [running]:
runtime.throw({0x10674ec, 0x10664a0})
/Users/edz/.g/versions/1.17.6/src/runtime/panic.go:1198 +0x71 fp=0xc00003a768 sp=0xc00003a738 pc=0x102c331
runtime.mapassign_fast64(0x10c3188, 0x10664a0, 0x1a6)
/Users/edz/.g/versions/1.17.6/src/runtime/map_fast64.go:101 +0x2c5 fp=0xc00003a7a0 sp=0xc00003a768 pc=0x100da05
gopl.io/demo/semaphore.testRace(...)
/Users/edz/gostudy/gopl.io/demo/semaphore/semaphore.go:30
gopl.io/demo/semaphore.Producer()
/Users/edz/gostudy/gopl.io/demo/semaphore/semaphore.go:24 +0x96 fp=0xc00003a7e0 sp=0xc00003a7a0 pc=0x1057cd6
runtime.goexit()
/Users/edz/.g/versions/1.17.6/src/runtime/asm_amd64.s:1581 +0x1 fp=0xc00003a7e8 sp=0xc00003a7e0 pc=0x1053921
created by main.main
/Users/edz/gostudy/gopl.io/demo/semaphore/main/main.go:9 +0x25
goroutine 1 [sleep]:
time.Sleep(0x1c9c380)
/Users/edz/.g/versions/1.17.6/src/runtime/time.go:193 +0x12e
main.main()
/Users/edz/gostudy/gopl.io/demo/semaphore/main/main.go:12 +0x3d
goroutine 6 [runnable]:
gopl.io/demo/semaphore.testRace(...)
/Users/edz/gostudy/gopl.io/demo/semaphore/semaphore.go:30
gopl.io/demo/semaphore.Consumer()
/Users/edz/gostudy/gopl.io/demo/semaphore/semaphore.go:38 +0x51
created by main.main
/Users/edz/gostudy/gopl.io/demo/semaphore/main/main.go:10 +0x33
Process finished with the exit code 2
func Producer() {
var item int
for {
item = producer_item()
down(&empty, "Producer empty")
down(&mutex, "Producer mutex")
insert_item(item)
testRace(item, 1)
up(&mutex, "Producer mutex")
up(&full, "Producer full")
}
}
func testRace(item int, value int) {
testMap[item] = value
}
func Consumer() {
var item int
for {
down(&full, "Consumer full")
down(&mutex, "Consumer mutex")
item = item_remove_item()
testRace(item, 2)
up(&mutex, "Consumer mutex")
up(&empty, "Consumer empty")
consumer_item(item)
}
}
结果正常:
insert_item: 298
down: wait... *v <= 0 ,*v: 0 tag: Consumer mutex
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 269 length: 30
up: 1 old: 0 tag: Consumer mutex
up: 271 old: 270 tag: Consumer empty
consumer_item item: 269
down: 27 old: 28 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 270 length: 29
up: 1 old: 0 tag: Consumer mutex
up: 272 old: 271 tag: Consumer empty
consumer_item item: 270
down: 26 old: 27 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 271 length: 28
up: 1 old: 0 tag: Consumer mutex
up: 273 old: 272 tag: Consumer empty
consumer_item item: 271
down: 25 old: 26 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 272 length: 27
up: 1 old: 0 tag: Consumer mutex
up: 274 old: 273 tag: Consumer empty
consumer_item item: 272
down: 24 old: 25 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 273 length: 26
up: 1 old: 0 tag: Consumer mutex
up: 275 old: 274 tag: Consumer empty
consumer_item item: 273
down: 23 old: 24 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 274 length: 25
up: 1 old: 0 tag: Consumer mutex
up: 276 old: 275 tag: Consumer empty
consumer_item item: 274
down: 22 old: 23 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 275 length: 24
up: 1 old: 0 tag: Consumer mutex
up: 277 old: 276 tag: Consumer empty
consumer_item item: 275
down: 21 old: 22 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 276 length: 23
up: 1 old: 0 tag: Consumer mutex
up: 278 old: 277 tag: Consumer empty
consumer_item item: 276
down: 20 old: 21 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 277 length: 22
up: 1 old: 0 tag: Consumer mutex
up: 279 old: 278 tag: Consumer empty
consumer_item item: 277
down: 19 old: 20 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 278 length: 21
up: 1 old: 0 tag: Consumer mutex
up: 280 old: 279 tag: Consumer empty
consumer_item item: 278
down: 18 old: 19 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 279 length: 20
up: 1 old: 0 tag: Consumer mutex
up: 281 old: 280 tag: Consumer empty
consumer_item item: 279
down: 17 old: 18 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 280 length: 19
up: 1 old: 0 tag: Consumer mutex
up: 282 old: 281 tag: Consumer empty
consumer_item item: 280
down: 16 old: 17 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 281 length: 18
up: 1 old: 0 tag: Consumer mutex
up: 283 old: 282 tag: Consumer empty
consumer_item item: 281
down: 15 old: 16 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 282 length: 17
up: 1 old: 0 tag: Consumer mutex
up: 284 old: 283 tag: Consumer empty
consumer_item item: 282
down: 14 old: 15 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 283 length: 16
up: 1 old: 0 tag: Consumer mutex
up: 285 old: 284 tag: Consumer empty
consumer_item item: 283
down: 13 old: 14 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
up: 1 old: 0 tag: Producer mutex
up: 14 old: 13 tag: Producer full
producer_item item: 299
down: 284 old: 285 tag: Producer empty
item_remove_item: 284 length: 15
up: 1 old: 0 tag: Consumer mutex
up: 285 old: 284 tag: Consumer empty
consumer_item item: 284
down: 13 old: 14 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 285 length: 14
up: 1 old: 0 tag: Consumer mutex
up: 286 old: 285 tag: Consumer empty
consumer_item item: 285
down: 12 old: 13 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 286 length: 13
up: 1 old: 0 tag: Consumer mutex
up: 287 old: 286 tag: Consumer empty
consumer_item item: 286
down: 11 old: 12 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 287 length: 12
up: 1 old: 0 tag: Consumer mutex
up: 288 old: 287 tag: Consumer empty
consumer_item item: 287
down: 10 old: 11 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 288 length: 11
up: 1 old: 0 tag: Consumer mutex
up: 289 old: 288 tag: Consumer empty
consumer_item item: 288
down: 9 old: 10 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 289 length: 10
up: 1 old: 0 tag: Consumer mutex
up: 290 old: 289 tag: Consumer empty
consumer_item item: 289
down: 8 old: 9 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 290 length: 9
up: 1 old: 0 tag: Consumer mutex
up: 291 old: 290 tag: Consumer empty
consumer_item item: 290
down: 7 old: 8 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 291 length: 8
up: 1 old: 0 tag: Consumer mutex
up: 292 old: 291 tag: Consumer empty
consumer_item item: 291
down: 6 old: 7 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 292 length: 7
up: 1 old: 0 tag: Consumer mutex
up: 293 old: 292 tag: Consumer empty
consumer_item item: 292
down: 5 old: 6 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 293 length: 6
up: 1 old: 0 tag: Consumer mutex
up: 294 old: 293 tag: Consumer empty
consumer_item item: 293
down: 4 old: 5 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 294 length: 5
up: 1 old: 0 tag: Consumer mutex
up: 295 old: 294 tag: Consumer empty
consumer_item item: 294
down: 3 old: 4 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 295 length: 4
up: 1 old: 0 tag: Consumer mutex
up: 296 old: 295 tag: Consumer empty
consumer_item item: 295
down: 2 old: 3 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 296 length: 3
up: 1 old: 0 tag: Consumer mutex
up: 297 old: 296 tag: Consumer empty
consumer_item item: 296
down: 1 old: 2 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 297 length: 2
up: 1 old: 0 tag: Consumer mutex
up: 298 old: 297 tag: Consumer empty
consumer_item item: 297
down: 0 old: 1 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 298 length: 1
up: 1 old: 0 tag: Consumer mutex
up: 299 old: 298 tag: Consumer empty
consumer_item item: 298
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: wait... *v <= 0 ,*v: 0 tag: Producer mutex
down: 0 old: 1 tag: Producer mutex
insert_item: 299
up: 1 old: 0 tag: Producer mutex
up: 1 old: 0 tag: Producer full
producer_item item: 300
down: 298 old: 299 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 300
up: 1 old: 0 tag: Producer mutex
up: 2 old: 1 tag: Producer full
producer_item item: 301
down: 297 old: 298 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 301
up: 1 old: 0 tag: Producer mutex
up: 3 old: 2 tag: Producer full
producer_item item: 302
down: 296 old: 297 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 302
up: 1 old: 0 tag: Producer mutex
up: 4 old: 3 tag: Producer full
producer_item item: 303
down: 295 old: 296 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 303
up: 1 old: 0 tag: Producer mutex
up: 5 old: 4 tag: Producer full
producer_item item: 304
down: 294 old: 295 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 304
down: wait... *v <= 0 ,*v: 1 tag: Consumer full
down: 4 old: 5 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 299 length: 6
up: 1 old: 0 tag: Consumer mutex
up: 295 old: 294 tag: Consumer empty
consumer_item item: 299
down: 3 old: 4 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 300 length: 5
up: 1 old: 0 tag: Consumer mutex
up: 296 old: 295 tag: Consumer empty
consumer_item item: 300
down: 2 old: 3 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 301 length: 4
up: 1 old: 0 tag: Consumer mutex
up: 297 old: 296 tag: Consumer empty
consumer_item item: 301
down: 1 old: 2 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 302 length: 3
up: 1 old: 0 tag: Consumer mutex
up: 298 old: 297 tag: Consumer empty
consumer_item item: 302
down: 0 old: 1 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 303 length: 2
up: 1 old: 0 tag: Consumer mutex
up: 299 old: 298 tag: Consumer empty
consumer_item item: 303
up: 1 old: 0 tag: Producer mutex
up: 1 old: 0 tag: Producer full
producer_item item: 305
down: 298 old: 299 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 305
up: 1 old: 0 tag: Producer mutex
up: 2 old: 1 tag: Producer full
producer_item item: 306
down: 297 old: 298 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 306
up: 1 old: 0 tag: Producer mutex
up: 3 old: 2 tag: Producer full
producer_item item: 307
down: 296 old: 297 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 307
up: 1 old: 0 tag: Producer mutex
up: 4 old: 3 tag: Producer full
producer_item item: 308
down: 295 old: 296 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 308
up: 1 old: 0 tag: Producer mutex
up: 5 old: 4 tag: Producer full
producer_item item: 309
down: 294 old: 295 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 309
up: 1 old: 0 tag: Producer mutex
up: 6 old: 5 tag: Producer full
producer_item item: 310
down: 293 old: 294 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 310
up: 1 old: 0 tag: Producer mutex
up: 7 old: 6 tag: Producer full
producer_item item: 311
down: 292 old: 293 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 311
up: 1 old: 0 tag: Producer mutex
up: 8 old: 7 tag: Producer full
producer_item item: 312
down: 291 old: 292 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 312
down: wait... *v <= 0 ,*v: 0 tag: Consumer full
down: 7 old: 8 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 304 length: 9
up: 1 old: 0 tag: Consumer mutex
up: 292 old: 291 tag: Consumer empty
consumer_item item: 304
down: 6 old: 7 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 305 length: 8
up: 1 old: 0 tag: Consumer mutex
up: 293 old: 292 tag: Consumer empty
consumer_item item: 305
down: 5 old: 6 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 306 length: 7
up: 1 old: 0 tag: Consumer mutex
up: 294 old: 293 tag: Consumer empty
consumer_item item: 306
down: 4 old: 5 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 307 length: 6
up: 1 old: 0 tag: Consumer mutex
up: 295 old: 294 tag: Consumer empty
consumer_item item: 307
down: 3 old: 4 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 308 length: 5
up: 1 old: 0 tag: Consumer mutex
up: 296 old: 295 tag: Consumer empty
consumer_item item: 308
up: 1 old: 0 tag: Producer mutex
up: 3 old: 2 tag: Producer full
producer_item item: 313
down: 295 old: 296 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
down: 2 old: 3 tag: Consumer full
insert_item: 313
up: 1 old: 0 tag: Producer mutex
up: 4 old: 3 tag: Producer full
producer_item item: 314
down: 294 old: 295 tag: Producer empty
down: 0 old: 1 tag: Producer mutex
insert_item: 314
up: 1 old: 0 tag: Producer mutex
up: 5 old: 4 tag: Producer full
producer_item item: 315
down: wait... *v <= 0 ,*v: 1 tag: Consumer mutex
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 309 length: 6
up: 1 old: 0 tag: Consumer mutex
up: 294 old: 293 tag: Consumer empty
consumer_item item: 309
down: 4 old: 5 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 310 length: 5
up: 1 old: 0 tag: Consumer mutex
up: 295 old: 294 tag: Consumer empty
consumer_item item: 310
down: 3 old: 4 tag: Consumer full
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 311 length: 4
up: 1 old: 0 tag: Consumer mutex
up: 296 old: 295 tag: Consumer empty
consumer_item item: 311
down: 2 old: 3 tag: Consumer full
down: 293 old: 294 tag: Producer empty
down: wait... *v <= 0 ,*v: 0 tag: Producer mutex
down: wait... *v <= 0 ,*v: 0 tag: Producer mutex
down: 0 old: 1 tag: Consumer mutex
item_remove_item: 312 length: 3
down: wait... *v <= 0 ,*v: 0 tag: Producer mutex
down: 0 old: 1 tag: Producer mutex
main finished
up: 1 old: 0 tag: Consumer mutex
up: 297 old: 296 tag: Consumer empty
consumer_item item: 312
down: 1 old: 2 tag: Consumer full
insert_item: 315
up: 1 old:
Process finished with the exit code 0
Semaphores
http://boron.physics.metu.edu.tr/ozdogan/OperatingSystems/spring2004/week4/week4.pdf
Golang 五种原子性操作的用法详解 - 云+社区 - 腾讯云