Windows CRITICAL_SECTION реализована проще, чем мьютекс (что касается затрат на блокировку/разблокировку). За счет использования спин-блокировки и семафора для уменьшения числа переключений пользователя/ядра.
Мьютекс требует переключения контекста, даже если мьютекс в настоящее время не принадлежит / не заблокирован, где CRITICAL_SECTION потребует этого только после определенного периода времени, находящегося в блокировке спина (приводит к лучшей производительности).
Я новичок в Android Native dev, имея в виду Windows CRITICAL_SECTION, есть ли эквивалент в Native Android?
Есть ли что-нибудь легче, чем pthread_mutex_. @ Android? делает ли 'pthread_mutex_.' переключение контекста, даже если мьютекс еще не ~владел/заблокирован~ (как в Windows)?
Имея в виду быстрый вход/выход из критической секции Какова стоимость использования 'pthread_mutex_.'?
Есть ли спин-блокировка пользовательского режима @ Native Android?
Любая помощь будет оценена.
Надав в Софине
Ответ 1 · рейтинг 5 · caf
Нет, 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() довольно легкими.
Ответ 2 · рейтинг 3 · Gavin
Ниже приведен некоторый мьютекс 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!
}