Golang Rwmutex Read-write lock analysis

Source: Internet
Author: User
Tags mutex semaphore


Rwmutex: is a mutex-based read-write mutex, a goroutine can hold multiple read locks or a write lock, at the same time can only hold read lock or write lock



Data structure Design:


Type Rwmutex struct {
    w           mutex  //Mutex
    Writersem uint32//   write lock semaphore
    Readersem   uint32/Read lock semaphore
    readercount Int32//  read lock counter
    readerwait  int32  //Get write lock to wait for the number of read lock releases
}
Gets the Write lock
func (rw *rwmutex) lock () {
    if race. Enabled {
        _ = rw.w.state
        race. Disable ()
    }
    //First acquires a mutex
    Rw.w.lock ()
    //minus the maximum number of read locks, with 0-negative to indicate that the write lock has been obtained
    r: = Atomic. AddInt32 (&rw.readercount,-rwmutexmaxreaders) + rwmutexmaxreaders
    //sets the number of read locks to wait for release, and if so, suspends the acquisition of read locks Goroutine
    if r! = 0 && Atomic. AddInt32 (&rw.readerwait, r)! = 0 {
        //hang, monitor write lock semaphore
        Runtime_semacquire (&rw.writersem)
    }
    if Race. Enabled {
        race. Enable ()
        race. Acquire (unsafe. Pointer (&rw.readersem))
        race. Acquire (unsafe. Pointer (&rw.writersem))
    }
}


In order this should introduce the code that releases the write lock, but because there are a few logical variables that are important in obtaining a write lock, it is strongly dependent on acquiring a read lock, so let's talk about the logic to get the read lock.


// Get write lock
func (rw * RWMutex) Lock () {
     if race.Enabled {
         _ = rw.w.state
         race.Disable ()
     }
     // Get a mutex first
     rw.w.Lock ()
     // minus the maximum number of read locks, using 0-negative numbers to indicate that the write lock has been acquired
     r: = atomic.AddInt32 (& rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders
     // Set the number of read locks waiting to be released, if any, suspend the goroutine that acquired the read lock
     if r! = 0 && atomic.AddInt32 (& rw.readerWait, r)! = 0 {
         // Suspend, monitor write lock semaphore
         runtime_Semacquire (& rw.writerSem)
     }
     if race.Enabled {
         race.Enable ()
         race.Acquire (unsafe.Pointer (& rw.readerSem))
         race.Acquire (unsafe.Pointer (& rw.writerSem))
     }
}
// Obtain a read lock
func (rw * RWMutex) RLock () {
     if race.Enabled {
         _ = rw.w.state
         race.Disable ()
     }
    
     // Every time a read lock is acquired, readerCount + 1
     // If the write lock has been acquired, the readerCount is between -rwmutexMaxReaders and 0. At this time, the goroutine that acquired the read lock is suspended.
     // If the write lock has not been acquired, then readerCount> = 0, then no more
     // In this way, the positive and negative of readerCount becomes the judgment condition of the read lock and write lock mutual exclusion.

     if atomic.AddInt32 (& rw.readerCount, 1) <0 {
         // Hang, listen for readerSem semaphore
         runtime_Semacquire (& rw.readerSem)
     }
     if race.Enabled {
         race.Enable ()
         race.Acquire (unsafe.Pointer (& rw.readerSem))
     }
} 
Func (rw *rwmutex) Unlock () {
    if race. Enabled {
        _ = rw.w.state
        race. Release (unsafe. Pointer (&rw.readersem))
        race. Release (unsafe. Pointer (&rw.writersem))
        race. Disable ()
    }

    //Restore lock when the part Readercount
    r: = Atomic. AddInt32 (&rw.readercount, rwmutexmaxreaders)
    if R >= rwmutexmaxreaders {
        race. Enable ()
        Panic ("Sync:unlock of Unlocked Rwmutex")
    }
    //wake-up gets read lock all blocked Goroutine for
    i: = 0; i < in T (r); i++ {
        runtime_semrelease (&rw.readersem)
    }
    //Releases the mutex resource
    rw.w.unlock ()
    if race. Enabled {
        race. Enable ()
    }
}


Summarize:



The implementation of the read-write mutex is more skillful and requires several



1. Read lock can not block read lock, introduce Readercount implementation



2. The read lock needs to block the write lock until the read lock is released, introducing the READERSEM implementation



3. The write lock needs to block the read lock until the write lock is released, introducing the WIRTERSEM implementation



4. Write lock need to block write lock, introduce METUX implementation


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.