互斥鎖是併發編程的時候會用到的東西,它表示一份數據不能夠被兩個進程同時訪問.編程
// A Mutex is a mutual exclusion lock. // The zero value for a Mutex is an unlocked mutex. // // A Mutex must not be copied after first use. type Mutex struct { state int32 sema uint32 } // Lock locks m. // If the lock is already in use, the calling goroutine // blocks until the mutex is available. func (m *Mutex) Lock() { // Fast path: grab unlocked mutex. if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) { if race.Enabled { race.Acquire(unsafe.Pointer(m)) } return } // Slow path (outlined so that the fast path can be inlined) m.lockSlow() }
import ( "sync" ) const ( N = 10 ) func main() { data := 0 var lock sync.Mutex done := make(chan bool) for i := 0; i < N; i++ { go func() { lock.Lock() data += 1 if data == N { done <- true } lock.Unlock() }() } <- done }
pub struct Mutex<T: ?Sized> { // Note that this mutex is in a *box*, not inlined into the struct itself. // Once a native mutex has been used once, its address can never change (it // can't be moved). This mutex type can be safely moved at any time, so to // ensure that the native mutex is used correctly we box the inner mutex to // give it a constant address. inner: Box<sys::Mutex>, poison: poison::Flag, data: UnsafeCell<T>, } impl<T: ?Sized> Mutex<T> { pub fn lock(&self) -> LockResult<MutexGuard<'_, T>> { unsafe { self.inner.raw_lock(); MutexGuard::new(self) } } } pub struct MutexGuard<'a, T: ?Sized + 'a> { lock: &'a Mutex<T>, poison: poison::Guard, } impl<T: ?Sized> Drop for MutexGuard<'_, T> { #[inline] fn drop(&mut self) { unsafe { self.lock.poison.done(&self.poison); self.lock.inner.raw_unlock(); } } }
use std::sync::{Arc, Mutex}; use std::thread; use std::sync::mpsc::channel; fn main() { const N: usize = 10; let data = Arc::new(Mutex::new(0)); let (tx, rx) = channel(); for _ in 0..N { let (data, tx) = (Arc::clone(&data), tx.clone()); thread::spawn(move || { let mut data = data.lock().unwrap(); *data += 1; if *data == N { tx.send(()).unwrap(); } }); } println!("{:?}", rx.recv().unwrap()); }