Para que haja qualquer união, dois tópicos são necessários. Um tópico chama o outro tópico. Juntar -se a um tópico significa que, enquanto o tópico de chamada está em execução, ele parou em uma posição e aguardava o encadeamento chamado completar sua execução (até o fim), antes de continuar sua própria execução. Na posição em que o fio termina, há uma expressão de junção. Essa interrupção é chamada de bloqueio.
Se o encadeamento chamado estiver demorando muito para concluir e provavelmente fez o que o tópico de chamada espera. Após o desapego, se o encadeamento chamado concluir após o tópico de chamada, não deve haver problema. Destacando significa quebrar a junção (link).
Lembrar
Um thread é uma função de nível superior que foi incluída em um objeto de thread, instanciado da classe Thread. Instantar o fio com a função de nível superior significa chamar a função. Aqui está um programa simples de threads, com a declaração de junção:
#incluir
#incluir
usando namespace std;
void func ()
cout <<"… from thread!" <<'\n';
int main ()
Thread thd (func);
thd.juntar();
/* declarações */
retornar 0;
Existem dois tópicos aqui: o objeto, THD e a função principal (). A função principal é como o tópico principal. Observe a inclusão da biblioteca de threads. A saída é:
… De thread!
No prompt de comando, um programa C ++ 20 com threads deve ser comandado da seguinte maneira, para o compilador G ++:
g ++ -std = c ++ 2a amostra.amostra cc -lpthread -o.exe
Conteúdo do artigo
SINTAXET ()
A sintaxe do DETABE () é simples; isso é:
ThreadObject.destacar ()
Esta função de membro do objeto Thread retorna vazios. ThreadObject é o objeto de rosca do fio cuja função está executando. Quando a função de um thread está em execução, o thread é chamado de tópico de execução.
Um tópico só pode ser destacado depois de ser unido; Caso contrário, o tópico já está no estado destacado.
Ambiguidade de destacar no corpo do fio de chamada
No programa a seguir, o encadeamento chamado é destacado no corpo do tópico de chamada:
#incluir
#incluir
#incluir
usando namespace std;
string globl = string ("na terra!");
void func (String st)
String fin = "Living" + st;
cout <
int main ()
Thread Thr (func, GLOBL);
Thr.juntar();
Thr.retach ();
retornar 0;
A saída do computador do autor em tempo de execução foi:
Vivendo na terra!
rescindir chamado depois de jogar uma instância de 'std :: system_error'
o que (): argumento inválido
Abortado (núcleo despejado)
A saída adequada esperada deve ser apenas:
Vivendo na terra!
Quando um tópico termina sua execução, a implementação libera todos os recursos que possuía. Quando um tópico é unido, o corpo do tópico de chamada espera naquele ponto até que o fio chamado complete sua execução, então o corpo do tópico de chamada continua sua própria execução.
O problema da presença da saída adicional é que, embora o encadeamento chamado possa ter concluído sua tarefa dada a ele, seus recursos nem todos foram retirados, mas a função de destacar () causou o corpo da função de chamada para continuar executando. Na ausência da função DetArt (), o encadeamento chamado teria concluído, além de todos os seus recursos retirados; e a saída teria sido a simples linha única esperada.
Para convencer ainda mais o leitor, considere o seguinte programa, que é o mesmo que o acima, mas com as declarações de junção () e destacar () comentaram:
#incluir
#incluir
#incluir
usando namespace std;
string globl = string ("na terra!");
void func (String st)
String fin = "Living" + st;
cout <
int main ()
Thread Thr (func, GLOBL);
// thr.juntar();
// thr.retach ();
retornar 0;
A saída do computador do autor é:
rescindir chamado sem uma exceção ativa
Abortado (núcleo despejado)
A função principal () passou até o final sem esperar que o tópico faça qualquer coisa. E assim, o fio não conseguiu exibir sua saída.
Nome do tópico no escopo global
Um tópico pode ser instanciado no escopo global. O programa a seguir ilustra o seguinte:
#incluir
#incluir
usando namespace std;
thread thr;
void func ()
cout <<"the first line" <cout <<"the second line" <
int main ()
thr = thread (func);
Thr.juntar();
retornar 0;
A saída é:
a primeira linha
a segunda linha
Antes da função, o func () é definido no programa; Aí está a declaração,
thread thr;
que instancia o tópico, thr. Neste ponto, o THR não tem uma função correspondente. Na função Main (), a primeira afirmação é:
thr = thread (func);
O lado direito desta declaração cria um tópico sem nome e atribui o fio à variável Thread, thr. Dessa forma, THR adquire uma função. A próxima declaração se junta ao tópico chamado.
Destacando dentro do fio chamado
Uma maneira melhor de destacar um fio é fazê -lo dentro do corpo do fio chamado. Nesse caso, o objeto Thread teria que ser criado no escopo global, como ilustrado acima. Em seguida, a declaração destacar estará no corpo do fio chamado, onde o destacamento deve ocorrer. O programa a seguir ilustra o seguinte:
#incluir
#incluir
usando namespace std;
thread thr;
void func ()
cout <<"the first line" <Thr.retach ();
cout <<"the second line" <
int main ()
thr = thread (func);
Thr.juntar();
cout <<"main() function line" <retornar 0;
A saída é:
a primeira linha
a segunda linha
linha de função main ()
Nenhuma mensagem de erro foi emitida em tempo de execução. A declaração de junção () esperava que o tópico fosse executado antes que o corpo da função principal () pudesse continuar. Isso aconteceu apesar do fato de o fio chamado ter sido destacado no meio de sua execução, com a declaração,
Thr.retach ();
E assim a função principal () (thread principal) continuou após a conclusão do fio chamado, com todos os seus recursos divulgados pela implementação. Na segunda metade do fio chamado, o fio chamado já estava desapegado, embora o tópico de chamada ainda estivesse esperando.
O programa começa com a inclusão da biblioteca iostream para o objeto Cout. Em seguida, há a inclusão da biblioteca de threads, que é uma obrigação. Depois, há a instanciação do fio, Thr, sem uma função. A função que ele usará é definida logo após. Esta função tem a declaração destacada do objeto, th em seu corpo.
No corpo da função main (), a primeira afirmação cria um fio de uma função, mas sem nome. Este tópico é então atribuído a THR. Então, o THR agora tem uma função, com a vantagem de que foi criada no escopo global, para que pudesse ser visto em func ().
A próxima declaração se junta ao corpo da função da função Main () ao thread chamado. O tópico foi chamado na primeira declaração da função principal (). Neste ponto, o corpo principal () da função espera que o Thread chamado seja atingido até o fim e todos os seus recursos lançados, embora tenha sido destacado no meio. A função junção () cumpre seu dever, desde que qualquer coisa dentro do encadeamento chamado seja legítimo.
E assim a execução continua com a função principal depois que o encadeamento chamado foi lançado com sucesso, conforme previsto (com todos os seus recursos lançados). Por isso,
“Main () Linha de função”
é produzido após todas as saídas do encadeamento chamado.
Conclusão
Definir um fio significa que o encadeamento chamado pode continuar a executar, enquanto o encadeamento o chamado também pode continuar a executar. Isto é, o tópico de chamada não continua mais esperando (bloco), depois de se juntar. Isso pode aumentar a velocidade de ambos os threads, permitindo que eles funcionem em paralelo e aumentando a velocidade de todo o programa. Nesse caso, é melhor destacar o fio em seu corpo, onde a comunicação entre eles não ocorrerá mais. Além disso, para conseguir isso, deixe a variável de thread ser criada no escopo global sem sua função. Na função Main () do programa C ++, um tópico anônimo, com a função de interesse, pode ser criado e atribuído à variável Thread. Esta etapa chama a função do thread e, portanto, chama o tópico.
Então, após a declaração destacada, a declaração de junção () não tem mais seu papel normal de esperar (bloqueando o tópico de chamada), embora ainda possa esperar. Não é recomendável destacar o encadeamento chamado do tópico de chamada.