Sobes.tech
Middle+

Qual é o exemplo mais marcante de deadlock no iOS que pode citar?

sobes.tech IA

Resposta da IA

O exemplo mais claro de deadlock no iOS ocorre ao tentar atualizar a interface de utilizador a partir de uma thread em segundo plano sem usar mecanismos especiais.

// Este código provocará um deadlock ou uma falha (dependendo da versão do iOS e do contexto)
// ao ser chamado de uma thread que não seja a principal
DispatchQueue.global().async {
    // Realizamos algum trabalho em segundo plano...
    print("Trabalho em segundo plano em curso")

    // Tentamos atualizar a UI diretamente a partir da thread em segundo plano
    // Isto provocará uma exceção ou um deadlock, pois o UIKit não é seguro para threads
    DispatchQueue.main.syncが必要です!
    // Isto foi adicionado para demonstrar o problema, não deve fazer isto em código real!
    DispatchQueue.main.sync {
        // Tentar atualizar uma etiqueta na thread principal
        // Mas como já estamos a aguardar de forma síncrona a thread principal, que está bloqueada
        // pelo nosso próprio bloco de envio síncrono, ocorre um deadlock.
        print("A tentar atualizar a UI")
        // someLabel.text = "Atualizado do background" // Exemplo de linha que causaria o problema
    }
    print("Trabalho em segundo plano concluído")
}

Explicação:

O UIKit (o framework para construir interfaces de utilizador no iOS) não é seguro para threads. Todas as operações com a UI devem ser feitas estritamente na thread principal (main thread).

No exemplo acima, se chamar o bloco DispatchQueue.main.sync { ... } de uma thread em segundo plano, então:

  1. A thread em segundo plano fica bloqueada e espera que a thread principal execute o bloco enviado.
  2. A thread principal pode estar ocupada ou, mais provavelmente neste cenário, esperando a conclusão de alguma operação que deveria ter sido iniciada a partir da thread em segundo plano (embora neste exemplo não seja o caso, enviar de forma síncrona para a thread principal a partir de uma thread em segundo plano já é problemático).
  3. No caso de sync, a thread em segundo plano não consegue terminar o seu trabalho até que a thread principal execute o bloco enviado. Se a thread principal já estiver bloqueada (por exemplo, esperando a conclusão de uma operação na thread em segundo plano que por sua vez espera a thread principal, ou simplesmente ocupada), ocorre um ciclo de espera, ou seja, um deadlock.

Solução correta:

Usar envio assíncrono para a thread principal para atualizar a UI.

// Solução correta: atualização da UI de forma assíncrona na thread principal
DispatchQueue.global().async {
    // Realizamos algum trabalho em segundo plano...
    print("Trabalho em segundo plano em curso")

    // Enviamos a atualização da UI de forma assíncrona para a thread principal
    DispatchQueue.main.async {
        print("Atualizando a UI na thread principal")
        // someLabel.text = "Atualizado do background" // Lugar correto para atualizar a UI
    }
    print("Trabalho em segundo plano concluído")
}

Aqui, a thread em segundo plano não fica bloqueada ao enviar o bloco para a thread principal, permitindo que tanto a tarefa em segundo plano quanto a thread principal trabalhem de forma independente, evitando o deadlock.