Condição da Programação Simultânea Java (2)

prefácio

artigo anteriorCondição da Programação Simultânea Java (1)O processo de implementação do método é apresentado await, e os seguintes pontos precisam ser focados:

  • Se o método for chamado primeiro interrupt, chamar await lançará diretamente uma exceção;
  • awaitMétodo e lockmétodo possuem uma fila de espera respectivamente;
  • interrupte signalpode acordar threads de espera awaitdele .

Este artigo apresenta principalmente o seguinte signalprocesso de execução do código-fonte:

sinal

// ConditionObject类
public final void signal() {
    if (!isHeldExclusively())
        throw new IllegalMonitorStateException();
    Node first = firstWaiter;
    if (first != null)
        doSignal(first);
}
protected final boolean isHeldExclusively() {
    return getExclusiveOwnerThread() == Thread.currentThread();
}
复制代码

Ao chamar signalo método, ele primeiro verificará se a thread atual é uma thread segurando um bloqueio. Caso contrário, ela não poderá ser ativada e uma exceção será lançada diretamente. Em seguida, obtenha o nó principal nulle ative-o se não for o nó principal.

signalO método precisa ser chamado após adquirir o bloqueio, caso contrário, IllegalMonitorStateExceptionuma exceção é lançada

private void doSignal(Node first) {
    do {
        if ( (firstWaiter = first.nextWaiter) == null)
            lastWaiter = null;
        first.nextWaiter = null;
    } while (!transferForSignal(first) &&
             (first = firstWaiter) != null);
}
复制代码

Ativar o nó principal precisa removê-lo da fila de espera condicional. A instrução if acima primeiro aponta o nó principal para o próximo bit. Se o próximo bit for, significa que não há nenhum nó na fila, então defina o nó nullfinal nó para null, e o nó principal O próximo nó do nó é naturalmente também null.

whileA condição de loop significa que, se o nó principal atual falhar ao alternar da fila de espera condicional para a fila síncrona, e o próximo nó não for, ative o próximo nó nullaté que um nó bem-sucedido seja ativado ou toda a fila seja percorrida.

final boolean transferForSignal(Node node) {
    if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
        return false;
    Node p = enq(node);
    int ws = p.waitStatus;
    if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
        LockSupport.unpark(node.thread);
    return true;
}
复制代码

O nó é convertido da fila de espera condicional para a fila de sincronização. Primeiro, por meio CASda modificação waitStatus, se for bem-sucedido, enqo nó pode ser adicionado ao final da fila de sincronização por meio do método e o nó predecessor é retornado.

Como os nós na fila de sincronização precisam ser ativados pelo nó predecessor, se o nó predecessor for cancelado ( waitStatus>0) ou waitStatusmodificado para Node.SIGNAL( -1) falhar, isso significa que o nó anterior não pode ativar o thread atual, portanto, neste momento, diretamente use unparko método para ativar o thread atual, para evitar que nunca seja ativado.

Resumir

signalO processo do método awaité muito mais simples que o método, e faz principalmente duas coisas:

  • Remova o nó do thread atual da fila de condições;
  • Adicione o nó do encadeamento atual ao final da fila de bloqueio síncrono.

おすすめ

転載: juejin.im/post/7229991597085622328