Problema de uso da biblioteca <pthread.h> de programação multithread do NDK

pergunta

Uma biblioteca de código aberto é usada no projeto, incluindo código C++ nativo, que possui muitas operações simultâneas, e a biblioteca <pthread.h> é usada para garantir a segurança do thread.

Entre eles, a sincronização de threads é realizada usando bloqueios de exclusão mútua. A situação normal do processo é:

  • Inicialize o bloqueio – pthread_mutex_init
  • Bloqueio – pthread_mutex_lock ou pthread_mutex_trylock
  • desbloquear – pthread_mutex_unlock
  • Bloqueio de destruição – pthread_mutex_destroy

No entanto, como a lógica é mais complicada, exceções de execução podem ocorrer ocasionalmente e os bloqueios são adicionados depois que o bloqueio é destruído.

Em seguida, haverá diferentes desempenhos em diferentes máquinas de teste, alguns podem ser executados normalmente, alguns estão travados e alguns até travam diretamente.

A/libc: FORTIFY: pthread_mutex_trylock called on a destroyed mutex (0xb511d6f8)
A/libc: Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 2775 (han.mynativeapp), pid 2775 (han.mynativeapp)

Analise os motivos

Para analisar a causa da exceção de sincronização de thread, use o seguinte código para simular a situação anormal:

#include <jni.h>
#include <string>
#include <malloc.h>
#include <pthread.h>
#include <android/log.h>

extern "C" JNIEXPORT jstring JNICALL
Java_com_shiyinghan_mynativeapp_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    
    
    std::string hello = "Hello from C++";
    pthread_mutex_t *mutex = static_cast<pthread_mutex_t *>(calloc(1, sizeof(*mutex)));
    pthread_mutex_init(mutex, NULL);
    pthread_mutex_lock(mutex);
    pthread_mutex_unlock(mutex);
    pthread_mutex_destroy(mutex);
    int r = pthread_mutex_trylock(mutex);
    __android_log_print(ANDROID_LOG_INFO,"stringFromJNI","pthread_mutex_trylock %p %d", mutex, r);
    return env->NewStringUTF(hello.c_str());
}

Em seguida, os resultados da execução usando diferentes versões do Android são:

versão do Android logcat Resultados do
6.0 I/stringFromJNI: pthread_mutex_trylock 0x557ef45d20 0 bloqueio com sucesso
8.1 I/stringFromJNI: pthread_mutex_trylock 0x557f13cc30 16 bloqueio falhou
10 A/libc: FORTIFY: pthread_mutex_trylock chamado em um mutex destruído (0xb511d6f8) O aplicativo falha
11 A/libc: FORTIFY: pthread_mutex_trylock chamado em um mutex destruído (0xb511d6f8) O aplicativo falha

Embora apenas quatro versões tenham sido selecionadas, não testei mais versões e não usei para comparar marcas diferentes. Testei apenas o emulador e duas marcas de celulares, mas pode-se observar que conforme a versão do Android aumenta , <pthread.h> biblioteca, a imposição de pthread mutex está ficando mais rigorosa . Depois que pthread_mutex_destroy destrói o bloqueio, a versão inferior ainda pode bloquear com êxito, a versão ligeiramente superior falhará ao bloquear e a versão mais recente causa diretamente a falha do aplicativo.

Teste no Linux

A camada inferior do Android é o kernel do Linux. O que acontecerá se ele for executado diretamente no Linux? O código é o seguinte:

#include <stdio.h>
#include <malloc.h>
#include <pthread.h>

int main() {
    
    
    pthread_mutex_t *mutex = calloc(1, sizeof(*mutex));
    pthread_mutex_init(mutex, NULL);
    pthread_mutex_lock(mutex);
    pthread_mutex_unlock(mutex);
    pthread_mutex_destroy(mutex);
    int r = pthread_mutex_trylock(mutex);
    printf("pthread_mutex_trylock %p %d\n", mutex, r);
    return 0;
}

O resultado da execução é:

versão Linux logcat Resultados do
centos 7.9 Linux versão 3.10.0 pthread_mutex_trylock 0xf31010 22 bloqueio falhou
Ubuntu 20.04.3 Linux versão 5.11.0 pthread_mutex_trylock 0x556bcaa062a0 22 bloqueio falhou

Pode-se observar que, embora a versão do Linux seja diferente, o resultado é que o bloqueio falha , mas não ocorre nenhum erro de execução.

Resumir

Ao comparar os resultados do teste de bloqueio anormal mutex, pode-se ver que a biblioteca <pthread.h> na parte inferior do Android tem sua própria implementação exclusiva, que é inconsistente com outras distribuições do Linux, e quanto maior a versão do Android, o < pthread.h> Bibliotecas com imposição mais rigorosa podem travar o aplicativo imediatamente.

Portanto, para garantir a máxima compatibilidade e robustez do programa NDK, no processo de uso da biblioteca <pthread.h> para realizar a sincronização de threads, é necessário garantir que a aplicação do mutex siga o processo normal de uso para evitar ocorrências semelhantes ao mutex sendo bloqueado. O caso de re-bloqueio após a destruição.

Acho que você gosta

Origin blog.csdn.net/hanshiying007/article/details/121810054
Recomendado
Clasificación