Cenários usando threads - causas e soluções para segurança de simultaneidade de threads

Quando compramos um computador, geralmente prestamos atenção especial em quantos núcleos e threads a CPU do computador possui. Porque isso geralmente determina a velocidade do computador

, e tudo isso pode ser encontrado no gerenciador de tarefas.

 

Neste momento, mesmo que você tenha sido exposto a operações multi-threaded, você pode ter dúvidas sobre o que é um thread.

De acordo com a Enciclopédia Baidu: Thread (Inglês: thread) é a menor unidade que o sistema operacional pode realizar o agendamento da operação . Ele está incluído no processo e é a unidade operacional real no processo . Um thread refere-se a um único fluxo sequencial de controle em um processo . Vários threads podem ser executados simultaneamente em um processo e cada thread executa tarefas diferentes em paralelo. No Unix System V e SunOS , também é chamado de processos leves (processos leves), mas os processos leves referem-se a encadeamentos do kernel (encadeamentos do kernel) e encadeamentos do usuário (encadeamentos do usuário) são chamados de encadeamentos.

Então, quando precisamos usar multithreading?

1 : Processe várias tarefas diferentes ao mesmo tempo
Por exemplo, um sistema de videoconferência:
1 : transmitir áudio
2 : Transmitir vídeo
3 : Compartilhar área de trabalho
2 : Processar várias tarefas idênticas ao mesmo tempo (também conhecido como simultaneidade )
Bola pequena 5000
1 : Um thread pesquisa todas as operações, como desenhar e mover a bola
Quando o número de bolas aumenta: a votação demora muito
Multi-thread para lidar com essas bolas:
Um único thread é responsável apenas por uma parte: digamos que um thread execute apenas mil
3: modo de pipeline
Uma cadeia de missão completa que tem
Tarefa 1 :
Tarefa 2 : requer que a tarefa 1 seja concluída
Tarefa 3 : Requer que a Tarefa 2 seja concluída

Isso permite o uso mais eficiente de cada encadeamento.

Então, o que é segurança de simultaneidade de threads?

Ao lidar com tarefas concorrentes, como várias threads operam no mesmo recurso, o tempo de operação não é escalonado, o que torna a operação na memória repetida, resultando em confusão de dados e causando problemas de segurança.

 Por exemplo: Organizamos tarefas para cada thread, ou seja, somando 1000 vezes a num.

Etapas da operação da pilha de threads: obtenha num da memória heap -->> copie a cópia num para a pilha de threads -->> execute a operação num++

——>>Retorne num e atribua-o a num na memória heap.

Isso parece estar em ordem, mas notamos que não necessariamente apenas um thread obtém num da memória heap ao mesmo tempo.

Se vários threads o obtiverem, a operação num++ será repetida, de modo que o número final seja menor que 3000++ e os dados estejam errados.

 Situações comuns:

1 : Leitura e leitura não causarão problemas de segurança de thread
2: A leitura e a escrita irão gerar
3 : Write write irá gerar

E como resolvemos esse problema?

Afinal, se esse dado representa o valor que está no seu banco, você não vai querer que esteja errado! ! !

Usando fechaduras ( sincronizadas) :

Sincronize blocos de código, bloqueie recursos e permita apenas que threads atualmente mantendo bloqueios de monitor acessem recursos

Pode ser entendido como: quando uma thread copia num na memória heap, a memória heap é temporariamente "bloqueada" e não pode ser acessada.

Somente quando o thread concluir a operação de num e atribuir num à memória heap, ele será "desbloqueado" para que outros threads continuem a competir para acessar a memória heap.

Isso pode não apenas garantir que a operação não seja repetida, os dados não estarão errados e, ao mesmo tempo, devido ao mecanismo de acesso competitivo, a velocidade da tarefa será bastante acelerada.

Os exemplos são os seguintes:

Classe de tarefa:

public class Task{

     static int num=0;//静态变量,处于堆内存中

    public static void main(String[] args) {

        Task tt = new Task();
        Thread t1=new Thread(new Threadsy(tt));
        t1.start();
        Thread t2=new Thread(new Threadsy(tt));
        t2.start();
        Thread t3=new Thread(new Threadsy(tt));
        t3.start();//创建并启动三个线程

        try {
            t1.join();
            t2.join();
            t3.join();
        } catch (InterruptedException e) {
            throw new RuntimeException (e);
        }//阻塞,直到线程全部完成,便于得到最终结果

        System.out.println(tt.num);//检验结果
        
    }
}

Classe Thready:

public class Threadsy implements Runnable {

    Task tt = new Task();
    public Threadsy(Task tt) {
        this.tt = tt;
    }//构析方法,便于取堆内存中的num。

    static Object object = new Object();//值得注意的是,Object要保证是静态变量,存在堆内存中,才可以通过它“锁住”堆内存的num

    public void run() {
            for (int i = 0; i < 1000; i++) {

                synchronized (object/*只能“锁”对象*/) {
                    tt.num++;
                }//给堆内存上锁,保证线程安全

        }
    }//线程操作方式
}

Os resultados são ambos:

tudo normal! ! !

 

E se removermos o bloqueio de recurso:

ou seja, erro de dados:

Para tarefas simultâneas, o uso de multithreading pode melhorar muito a eficiência, mas preste muita atenção aos problemas de segurança do thread!

 

Acho que você gosta

Origin blog.csdn.net/AkinanCZ/article/details/126058188
Recomendado
Clasificación