1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package sync provides basic synchronization primitives such as mutual 6 // exclusion locks. Other than the Once and WaitGroup types, most are intended 7 // for use by low-level library routines. Higher-level synchronization is 8 // better done via channels and communication. 9 // 10 // Values containing the types defined in this package should not be copied. 11 12 // sync 包提供了互斥锁这类的基本的同步原语. 13 // 除 Once 和 WaitGroup 之外的类型大多用于底层库的例程。 14 // 更高级的同步操作通过信道与通信进行。 15 // 16 // 在此包中定义的类型中包含的值不应当被复制。 17 package sync 18 19 import ( 20 "sync/atomic" 21 "unsafe" 22 ) 23 24 // A Mutex is a mutual exclusion lock. 25 // Mutexes can be created as part of other structures; 26 // the zero value for a Mutex is an unlocked mutex. 27 28 // Mutex 是一个互斥锁。 29 // Mutex 可作为其它结构的一部分来创建;Mutex 的零值即为已解锁的互斥体。 30 type Mutex struct { 31 state int32 32 sema uint32 33 } 34 35 // A Locker represents an object that can be locked and unlocked. 36 37 // Locker 表示可被锁定并解锁的对象。 38 type Locker interface { 39 Lock() 40 Unlock() 41 } 42 43 const ( 44 mutexLocked = 1 << iota // mutex is locked // 互斥体已锁定。 45 mutexWoken 46 mutexWaiterShift = iota 47 ) 48 49 // Lock locks m. 50 // If the lock is already in use, the calling goroutine 51 // blocks until the mutex is available. 52 53 // Lock 用于锁定 m。 54 // 若该锁正在使用,调用的Go程就会阻塞,直到该互斥体可用。 55 func (m *Mutex) Lock() { 56 // Fast path: grab unlocked mutex. 57 // 快速通道:抢占锁定的互斥体。 58 if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) { 59 if raceenabled { 60 raceAcquire(unsafe.Pointer(m)) 61 } 62 return 63 } 64 65 awoke := false 66 for { 67 old := m.state 68 new := old | mutexLocked 69 if old&mutexLocked != 0 { 70 new = old + 1<<mutexWaiterShift 71 } 72 if awoke { 73 // The goroutine has been woken from sleep, 74 // so we need to reset the flag in either case. 75 // 此Go程已从睡眠状态被唤醒,因此无论在哪种状态下, 76 // 我们都需要充值此标记。 77 new &^= mutexWoken 78 } 79 if atomic.CompareAndSwapInt32(&m.state, old, new) { 80 if old&mutexLocked == 0 { 81 break 82 } 83 runtime_Semacquire(&m.sema) 84 awoke = true 85 } 86 } 87 88 if raceenabled { 89 raceAcquire(unsafe.Pointer(m)) 90 } 91 } 92 93 // Unlock unlocks m. 94 // It is a run-time error if m is not locked on entry to Unlock. 95 // 96 // A locked Mutex is not associated with a particular goroutine. 97 // It is allowed for one goroutine to lock a Mutex and then 98 // arrange for another goroutine to unlock it. 99 100 // Unlock 用于解锁 m。 101 // 若 m 在进入 Unlock 前并未锁定,就会引发一个运行时错误。 102 // 103 // 已锁定的 Mutex 并不与特定的Go程相关联,这样便可让一个Go程锁定 104 // Mutex,然后安排其它Go程来解锁。 105 func (m *Mutex) Unlock() { 106 if raceenabled { 107 _ = m.state 108 raceRelease(unsafe.Pointer(m)) 109 } 110 111 // Fast path: drop lock bit. 112 // 快速通道:锁定位。 113 new := atomic.AddInt32(&m.state, -mutexLocked) 114 if (new+mutexLocked)&mutexLocked == 0 { 115 panic("sync: unlock of unlocked mutex") 116 } 117 118 old := new 119 for { 120 // If there are no waiters or a goroutine has already 121 // been woken or grabbed the lock, no need to wake anyone. 122 // 若没有等待者,或一个Go程已被唤醒,或该Go程已经抢占了该锁时, 123 // 就无需唤醒任何一个了。 124 if old>>mutexWaiterShift == 0 || old&(mutexLocked|mutexWoken) != 0 { 125 return 126 } 127 // Grab the right to wake someone. 128 // 抢占权利来唤醒某一个。 129 new = (old - 1<<mutexWaiterShift) | mutexWoken 130 if atomic.CompareAndSwapInt32(&m.state, old, new) { 131 runtime_Semrelease(&m.sema) 132 return 133 } 134 old = m.state 135 } 136 } 137