Simultaneidade de ferrugem

Simultaneidade de ferrugem
A simultaneidade refere -se a um recurso que permite que partes independentes de um programa sejam executadas paralelas a outras seções do código. A concorrência permite que diferentes partes de um programa sejam executadas simultaneamente, melhorando o desempenho.

Vamos passear pela floresta de programação de simultaneidade na linguagem de programação de ferrugem. Lembre -se de que este artigo não foi projetado para ser um guia completo para programação de simultaneidade. Ele serve apenas como base para expandir e criar aplicativos mais complexos.

Processos e threads

Quando escrevemos um programa normal e o executamos em um sistema de destino, o sistema operacional host executa o código em um processo. Um processo refere -se a uma unidade de um executável especificado.

No entanto, em sistemas e aplicativos modernos, você tem partes do mesmo código executadas simultaneamente usando threads.

Na maioria dos casos, você costuma ouvir o termo multi-threading usado onde ocorre a simultaneidade. Isso ocorre porque estamos basicamente gerando vários tópicos e permitindo que eles corram paralelos um ao outro.

Vamos fazer um programa básico para ilustrar como um programa normal funciona e como usar a simultaneidade para melhorá -lo.

Considere um programa com dois loops como mostrado:

use std :: thread;
Use std :: time :: duração;
fn main ()
para i em 0… = 5
println!("", eu);
// durma por 1000ms
Thread :: Sleep (Duração :: From_millis (1000));

para i em 0… = 5
println!("", eu);
Thread :: Sleep (Duração :: From_millis (1000));

No código de exemplo acima, temos dois loops que iteram de 0 a 5. No entanto, em cada iteração, dormimos por 1000 milissegundos.

O método do thread :: Sleep nos permite colocar um tópico específico para dormir para a duração especificada.

Se você executar o código acima, perceberá que o primeiro loop aguarda a conclusão do segundo loop antes de começar a executar.

Isso ocorre porque ambos os loops estão em um único tópico.

Se queremos que ambos os loops funcionem simultaneamente, precisamos colocá -los em diferentes tópicos.

Rust Criar thread

Podemos criar novos threads usando o módulo de thread. Faz parte da biblioteca padrão e nos fornece um conjunto de ferramentas e funções para trabalhar com threads.

Podemos importá -lo usando a instrução:

use std :: thread;

Também precisamos do módulo de duração do tópico do tempo. Podemos importá -lo como:

Use std :: time :: duração

Para criar um novo tópico em ferrugem, use o tópico :: Spawn Method. Este método leva um fechamento como argumento.

O fechamento, neste caso, define o código a ser executado dentro do tópico.

A sintaxe é como mostrado abaixo:

thread :: spawn (|| fechamento)

Vamos refinar o código anterior e colocar cada construção em um tópico separado. O código de exemplo é como mostrado:

use std :: thread;
Use std :: time :: duração;
fn main ()
// Crie um novo tópico
std :: thread :: spawn (mova ||
para i em 0… = 5
println!("", eu);
Thread :: Sleep (Duração :: From_millis (1000));

);
para i em 0… = 5
println!("", eu);
Thread :: Sleep (Duração :: From_millis (1000));

No programa de exemplo acima, criamos um novo thread usando o thread :: Spawn Função e passamos o primeiro loop como o fechamento.

No tópico principal, executamos o segundo loop. Isso permite que ambos os loops funcionem simultaneamente. O código acima deve retornar a saída como:

0
0
1
1
2
2
3
3
4
4
5
5

O que acontece se o tópico principal sair antes que o thread "interno" seja concluído? Um exemplo é como mostrado abaixo:

use std :: thread;
Use std :: time :: duração;
fn main ()
// thread interno
std :: thread :: spawn (mova ||
para i em 0… = 5
println!("", eu);
Thread :: Sleep (Duração :: From_millis (1000));

);
// principal
para i em 0… = 5
println!("", eu);
Thread :: Sleep (Duração :: From_millis (2));

Neste exemplo, o tópico principal leva menos tempo para dormir e, portanto, será mais rápido antes que o tópico interno seja concluído.

Nesse caso, o fio interno só será executado enquanto o tópico principal está em execução. O código acima retornará a saída incompleta como:

0
0
1
2
3
4
5

Isso ocorre porque o tópico "interno" é encerrado antes da conclusão.

Alças de junção de ferrugem

Vimos como um tópico se comporta se o tópico principal sair antes de concluir. Podemos juntar -se às duas alças para resolver esse caso e deixar o outro tópico esperar por outro.

Juntar alças permitirá que o tópico principal aguarde os outros threads antes do término.

Para unir as alças, usamos o método de junção, conforme mostrado na sintaxe abaixo:

deixe handle_name = thread :: spawn (fechamento);
handle_name.juntar().desembrulhar();

Vamos redefinir nosso exemplo de loop, onde o tópico principal sai mais cedo.

use std :: thread;
Use std :: time :: duração;
fn main ()
Deixe Handle = std :: thread :: spawn (mova ||
para i em 0… = 5
println!("", eu);
Thread :: Sleep (Duração :: From_millis (1000));

);
para i em 0… = 5
println!("", eu);
Thread :: Sleep (Duração :: From_millis (2));

// Juntar alça
lidar.juntar().desembrulhar();

No código de exemplo acima, criamos uma variável de alça que segura o tópico. Em seguida, juntamos o thread usando o método junção ().

O método do desembrulhamento nos permite lidar com erros.

Como o tópico principal está dormindo por um tempo mais curto, ele deve ser concluído antes do tópico "interno". No entanto, ele deve esperar o outro tópico sair devido ao método de junção.

A saída é como mostrado:

0
0
1
2
3
4
5
1
2
3
4
5

Observe que o encadeamento principal produz todos os valores em curta duração e aguarda a conclusão do outro thread.

Fechamento de movimentação do fio da ferrugem

Você deve ter notado a palavra -chave de movimento dentro do fechamento do tópico em nosso exemplo anterior. O fechamento do movimento é usado com o método Thread :: Spawn para permitir o compartilhamento de dados entre threads.

Usando a palavra -chave mover, podemos permitir que um tópico transfira a propriedade dos valores para outro thread.

Tome um exemplo de programa abaixo:

use std :: thread;
Use std :: time :: duração;
fn main ()
deixe arr = [1,2,3,4,5];
Deixe Handle = std :: thread :: spawn (||
para eu em arr.iter ()
println!("", eu);
Thread :: Sleep (Duração :: From_millis (100));

);
lidar.juntar().desembrulhar();

No código acima, declaramos uma matriz chamada ARR no tópico principal. Em seguida, geramos um novo tópico sem o fechamento de movimentos.

Nota: Como estamos tentando acessar o Array ARR e torná -lo parte do ambiente de fechamento, a compilação falhará, pois não está disponível nesse tópico.

Podemos usar a palavra -chave mover para forçar o fechamento no tópico para se apropriar da matriz.

Podemos corrigir o código acima adicionando o fechamento da movimentação como mostrado:

use std :: thread;
Use std :: time :: duração;
fn main ()
deixe arr = [1,2,3,4,5];
Deixe Handle = std :: thread :: spawn (mova ||
para eu em arr.iter ()
println!("", eu);
Thread :: Sleep (Duração :: From_millis (100));

);
lidar.juntar().desembrulhar();

Isso permite que o tópico assuma a propriedade da matriz e a itere. Isso deve retornar:

1
2
3
4
5

Conclusão

Esse foram os fundamentos da programação simultânea na linguagem de programação de ferrugem. Embora este artigo sirva como uma base concreta para a simultaneidade da ferrugem, ele não cobre conceitos avançados. Você pode verificar a documentação para obter detalhes.