Oi Felipe, tudo bem?
O modificador volatile basicamente informa a JVM para ter cuidado com as Threads que estão sendo executadas simultaneamente. Essencialmente, volatile é usado para indicar que o valor de uma variável será modificado por diferentes threads.
Declarar uma variável Java com volatile significa:
O valor dessa variável nunca será armazenado em cache localmente: todas as leituras e gravações irão direto para a "main memory"
O acesso à variável atua como se estivesse dentro de um bloco sincronizado.
Por outro lado, declarar uma variável static em Java significa que haverá apenas uma cópia dessa variável para todas as instâncias daquele objeto, independentemente de quantos objetos da classe forem criados. A variável estará acessível mesmo sem nenhum Objeto criado. No entanto, as Threads podem ter valores armazenados localmente no "main memory", o que é um problema.
Isso significa que, se duas Threads atualizarem uma variável do mesmo Objeto simultaneamente e a variável não for declarada como volatile, pode haver um caso em que uma das Threads tenha em cache um valor antigo.
Mesmo se você acessar um valor estático por meio de várias Threads, cada thread pode ter sua cópia em cache local! Para evitar isso, você pode declarar a variável como static volatile e isso forçará a Thread a ler sempre do valor global (sem cache).
Espero ter ajudado.
Abraço! ;)