Синхронизация потоков @ Родной Android - PullRequest
1 голос
/ 16 марта 2012

Windows CRITICAL_SECTION реализована более легким, чем мьютекс (что касается стоимости перфорирования блокировки / разблокировки), используя спин-блокировку и семафор для уменьшения количества переключений между пользователем и ядром.

Мьютекс требует контекстапереключаться, даже если мьютекс в настоящее время не принадлежит / не заблокирован, где CRITICAL_SECTION будет требовать этого только после определенного периода времени, когда грешит на спин-блокировку (приводит к лучшей производительности).

Я новичок в Android Native dev, имеяв виду windows CRITICAL_SECTION, есть ли аналог в родном Android?

Есть ли что-нибудь легче, чем pthread_mutex_ . @ Android?pthread_mutex_ . 'навязывает переключение контекста, даже если мьютекс еще не ~ принадлежит / не заблокирован ~ (как в windows)?

Имея в виду быстрый вход / выход из критической секции Чтостоимость использования pthread_mutex_ . 'навязывается?

Есть ли спин-блокировка в пользовательском режиме @ Native Android?

Любая помощь будет оценена.

Надав у Софина

Ответы [ 2 ]

5 голосов
/ 20 марта 2012

Нет, pthread_mutex_lock() в Android Bionic libc не навязывает переключение контекста для блокировки нормального мьютекса в неконтролируемом состоянии - используется простое атомарное сравнение и обмен, за которым следует память барьер. Аналогично, для разблокировки мьютекса не требуется запись в ядре, если на нем нет ожидающего процесса.

Вы можете найти Bionic-реализацию pthread_mutex_lock() и pthread_mutex_unlock() в libc/bionic/pthread.c в источниках Bionic libc и увидеть это сами.

В целом вы можете считать pthread_mutex_lock() / pthread_mutex_unlock() достаточно легким.

3 голосов
/ 16 марта 2012

Ниже приведен пример инкапсуляции pthread мьютекса в стиль Windows. CRITICAL_SECTION

typedef struct tagCRITICAL_SECTION {
  pthread_mutex_t     _mutex;
  pthread_mutexattr_t _mutexattr;
} CRITICAL_SECTION, *LPCRITICAL_SECTION;


static inline
VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) {
  //  printf("[init]  %0x\n", (UINT)lpCriticalSection);
  int ret;
  ret = pthread_mutexattr_init(&(lpCriticalSection->_mutexattr));
  assert(ret==0);
#if defined (__APPLE__) || defined(__linux__)
    pthread_mutexattr_settype(&lpCriticalSection->_mutexattr, PTHREAD_MUTEX_RECURSIVE);
#elif ANDROID
    // Do nothing
#else
  lpCriticalSection->_mutexattr.__mutexkind = PTHREAD_MUTEX_RECURSIVE_NP;
#endif
  ret = pthread_mutex_init(&(lpCriticalSection->_mutex),
                           &(lpCriticalSection->_mutexattr));
  assert(ret==0);
}

static inline
VOID DeleteCriticalSection    (LPCRITICAL_SECTION lpCriticalSection) {
  int ret;
  ret = pthread_mutex_destroy    (&(lpCriticalSection->_mutex));
  assert(ret==0);
  ret = pthread_mutexattr_destroy(&(lpCriticalSection->_mutexattr));
  assert(ret==0);
}

static inline
VOID EnterCriticalSection     (LPCRITICAL_SECTION lpCriticalSection) {
  int ret;
  ret = pthread_mutex_lock(&(lpCriticalSection)->_mutex);
  assert(ret==0);
}

static inline
BOOL TryEnterCriticalSection     (LPCRITICAL_SECTION lpCriticalSection) {
  int ret;
  ret = pthread_mutex_trylock(&(lpCriticalSection)->_mutex);

  return ret == 0;
}

static inline
VOID LeaveCriticalSection     (LPCRITICAL_SECTION lpCriticalSection) {
  int ret;
  ret = pthread_mutex_unlock(&(lpCriticalSection->_mutex));
  // ret==1 means mutex is owned by another thread!
}
...