Синхронизация потоков @ Родной Android

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

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

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

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

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

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

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

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


person NadavRub    schedule 16.03.2012    source источник
comment
есть ли у вас какое-либо представление о блокировке/разблокировке устройства Android на собственном уровне, то есть на c/c++.   -  person CoDe    schedule 08.06.2012


Ответы (2)


Нет, 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() довольно легкими.

person caf    schedule 20.03.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!
}
person Gavin    schedule 16.03.2012
comment
Эта реализация очень удобна, TnX!!! тем не менее, он просто обертывает мьютекс aounf pthread без реализации логики спин-блокировки. Кто-нибудь знает о реализации спин-блокировки пользовательского режима? - person NadavRub; 16.03.2012