Почему sync.Mutex существует? - PullRequest
0 голосов
/ 04 марта 2019

Почему sync.Mutex существует, а у нас sync.RWMutex?Я могу заблокировать / разблокировать rw mutex.В чем основное различие между ними?

Ответы [ 2 ]

0 голосов
/ 05 марта 2019

Часть, занимающая больше места, как упомянуто @icza, также менее эффективна с точки зрения времени выполнения.

Если мы посмотрим на исходный код RWMutex.Lock:

// Lock locks rw for writing.
// If the lock is already locked for reading or writing,
// Lock blocks until the lock is available.
func (rw *RWMutex) Lock() {
    if race.Enabled {
        _ = rw.w.state
        race.Disable()
    }
    // First, resolve competition with other writers.
    rw.w.Lock()
    // Announce to readers there is a pending writer.
    r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders
    // Wait for active readers.
    if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
        runtime_SemacquireMutex(&rw.writerSem, false)
    }
    if race.Enabled {
        race.Enable()
        race.Acquire(unsafe.Pointer(&rw.readerSem))
        race.Acquire(unsafe.Pointer(&rw.writerSem))
    }
}

Мы можем видеть, что он вызывает Mutex.Lock, следовательно, он занимает то же время, что и Mutex.Lock, плюс все остальные вещи, которые он делает.

Мы видим вызов atomic.AddInt32, runtime_SemacquireMutex идругие методы объекта race, это будет иметь накладные расходы.

0 голосов
/ 04 марта 2019

Это правда, что вы можете использовать sync.RWMutex всякий раз, когда вам нужно sync.Mutex.

Я думаю, что оба существуют, потому что есть много случаевкогда достаточно sync.Mutex (вам не нужна блокировка на уровне чтения и записи), а реализация sync.Mutex проще: требует гораздо меньше памяти и, скорее всего, быстрее.

sync.Mutexвсего 8 байтов:

type Mutex struct {
    state int32
    sema  uint32
}

В то время как sync.RWMutex равен 8 + 16 = 24 байта (включая sync.Mutex):

type RWMutex struct {
    w           Mutex  // held if there are pending writers
    writerSem   uint32 // semaphore for writers to wait for completing readers
    readerSem   uint32 // semaphore for readers to wait for completing writers
    readerCount int32  // number of pending readers
    readerWait  int32  // number of departing readers
}

Да, можно сказать 8 или 24байты не должны иметь значения.И это не так долго, пока у вас есть только несколько мьютексов.

Но нередко помещать мьютекс в структуру, которую он должен защищать (либо встраивать, либо в обычное именованное поле).Теперь, если у вас есть кусочек этих структурных значений, может быть, даже тысячи, тогда да, это будет заметно.

Кроме того, если вам просто нужен мьютекс, sync.Mutex дает вам меньше шансов назлоупотребление им (вы не можете случайно вызвать RLock(), потому что у него нет этого метода).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...