Thanks to visit codestin.com
Credit goes to go-zh.org

...
运行 格式化

Source file src/sync/mutex.go

     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	

View as plain text