Golang in sync. Rwmutex and Sync.mutex differences

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed. The Golang Sync package implements two types of lock mutexes (mutexes) and Rwmutex (read and write locks), where Rwmutex is implemented based on mutexes, and read-only locks are implemented using similar functions as reference counters.

Type Mutex

func (M *mutex) Lock ()
func (M *mutex) Unlock ()
type Rwmutex
func (rw *rwmutex) Lock ()
func (rw *rwmutex) rlock ()
func (rw *rwmutex) rlocker () Locker
func (rw *rwmutex) runlock ()

Func (rw *rwmutex) Unlock ()


Where the mutex is a mutex, lock () lock, Unlock () Unlock, use lock () lock, you can not lock it again, until it is unlocked with Unlock (), it can be locked again. For read-write uncertainty scenarios, where there is no obvious difference between read and write times, and only one read or write is allowed, the lock leaf is called a global lock.

Func (M *mutex) Unlock () is used to unlock m, which can cause a run error if not locked before using Unlock ().

A locked mutex is not associated with a particular goroutine, so it can be locked with one goroutine and then unlocked with another goroutine.

Example of normal operation:


When unlock () is used before lock (), an error is raised


When the lock is locked again before unlocking, the deadlock state

Package Mainimport ("FMT" "Sync") func main () {var l *sync. MUTEXL = new (sync. Mutex) L.lock () fmt. Println ("1") L.lock ()} Run Result: 1 fatal error:all Goroutines is asleep-deadlock!

Rwmutex is a read-write lock that can add multiple read locks or a write lock, which is often used to read far more than the number of writes.

Func (rw *rwmutex) lock () write lock, if there are additional read and write locks before the write lock is added, lock blocks until the lock is available, and to ensure that the lock is finally available, the blocked lock call excludes the new reader from the acquired lock, that is, the write lock permission is higher than the read lock , write lock is preferred with write lock
The func (rw *rwmutex) Unlock () write lock unlocks, which causes a run-time error if no write lock is made .

Package Mainimport ("FMT" "Sync") func main () {var l *sync. RWMUTEXL = new (sync. Rwmutex) L.unlock () fmt. Println ("1") L.lock ()} Run Result: Panic:sync:unlock of unlocked mutex

Func (rw *rwmutex) rlock () read lock, when there is a write lock, cannot load read lock, when there is only read lock or no lock, can load read lock, read lock can load multiple, so for "read more write less" scenario

The func (rw *rwmutex) runlock () read lock unlocks, Runlock revokes a single rlock call, and it has no effect on other readers that exist simultaneously. If RW is not locked for reading, calling Runlock raises a run-time error ( Note: This is not the case in the go1.3 version, for example ).

Package Mainimport ("FMT" "Sync") func main () {var l *sync. RWMUTEXL = new (sync. Rwmutex) L.runlock ()//1 Runlockfmt.println ("1") L.rlock ()              } results: 1 But the program first attempts to unlock the read lock, and then read the lock, but no error, and can output normally.

Analysis: go1.3 version of the cause of this situation analysis, read the source code can be very clear to get results

Func (rw *rwmutex) Runlock () {if raceenabled {_ = Rw.w.stateracereleasemerge (unsafe. Pointer (&rw.writersem)) racedisable ()}<span style= "color: #FF0000;" >if Atomic. AddInt32 (&rw.readercount,-1) < 0 {//readercounter Initial value is 0, call Runlock to 1, continue to execute down/A writer is pending.if atomic. AddInt32 (&rw.readerwait,-1) = = 0 {//This time Readerwaiter becomes 1, 1-1 then becomes 0, you can continue the operation later. </span>//the last Reader unblocks the writer.runtime_semrelease (&rw.writersem)}}if raceenabled {raceEnable ( )}}

When the Runlock is more than Rlock, it will error and enter the deadlock. Examples are as follows:

Package Mainimport ("FMT" "Sync") type S struct {readercount Int32}func main () {l: = new (sync. Rwmutex) L.runlock () L.runlock ()//Deadlock FMT appears here. Println ("1") L.rlock ()} Run Result: 1 fatal error:all Goroutines is asleep-deadlock!

Summarize:

Therefore, in the go1.3 version, the operation allows Runlock to be earlier than the Rlock one, and can only be earlier than 1 (note: Although the code is allowed, but strongly deprecated), and after the Rlock must be used to lock to continue to use.

Related Article

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.