Como os methods estáticos sincronizados funcionam em Java?

Se eu tiver uma class util com methods estáticos que chamarão as funções do Hibernate para realizar o access básico aos dados. Eu estou querendo saber se fazer o método synchronized é a abordagem correta para garantir a segurança do thread.

Eu quero isso para impedir o access de informações para a mesma instância de database. No entanto, agora estou certo de que o código a seguir está impedindo que getObjectById seja chamado para todas as Classes quando for chamado por uma determinada class.

 public class Utils { public static synchronized Object getObjectById (Class objclass, Long id) { // call hibernate class Session session = new Configuration().configure().buildSessionFactory().openSession(); Object obj = session.load(objclass, id); session.close(); return obj; } // other static methods } 

   

    Ao usar sincronizado em um bloqueio de método estático, você sincronizará os methods e atributos de class (ao contrário dos methods e atributos da instância)

    Portanto, sua suposição está correta.

    Eu estou querendo saber se fazer o método sincronizado é a abordagem correta para garantir a segurança do thread.

    Na verdade não. Você deve deixar esse trabalho fazer seu RDBMS. Eles são bons nesse tipo de coisa.

    A única coisa que você conseguirá sincronizando o access ao database é tornar seu aplicativo terrivelmente lento. Além disso, no código que você postou, você está construindo uma Fábrica de Sessões a cada vez, dessa forma, seu aplicativo gastará mais tempo acessando o database do que realizando o trabalho real.

    Imagine o seguinte cenário:

    O cliente A e B tentam inserir informações diferentes no registro X da tabela T.

    Com sua abordagem, a única coisa que você está obtendo é certificar-se de que um é chamado após o outro, quando isso acontecer de qualquer maneira no database, porque o RDBMS impedirá que eles insiram metade da informação de A e metade de B ao mesmo tempo . O resultado será o mesmo, mas apenas 5 vezes (ou mais) mais lento.

    Provavelmente poderia ser melhor dar uma olhada no capítulo “Transações e concurrency” na documentação do Hibernate. Na maioria das vezes, os problemas que você está tentando resolver já foram resolvidos de uma forma muito melhor.

    Para abordar a questão mais geralmente …

    Tenha em mente que o uso de methods sincronizados é realmente apenas uma forma abreviada (suponha que a class seja o SomeClass):

     synchronized static void foo() { ... } 

    é o mesmo que

     static void foo() { synchronized(SomeClass.class) { ... } } 

    e

     synchronized void foo() { ... } 

    é o mesmo que

     void foo() { synchronized(this) { ... } } 

    Você pode usar qualquer object como o bloqueio. Se você quiser bloquear subconjuntos de methods estáticos,

     class SomeClass { private static final Object LOCK_1 = new Object() {}; private static final Object LOCK_2 = new Object() {}; static void foo() { synchronized(LOCK_1) {...} } static void fee() { synchronized(LOCK_1) {...} } static void fie() { synchronized(LOCK_2) {...} } static void fo() { synchronized(LOCK_2) {...} } } 

    (para methods não estáticos, você desejaria tornar os bloqueios campos não estáticos)

    Os methods estáticos usam a class como o object para bloqueio, que é Utils.class para o seu exemplo. Então sim, tudo bem.

    static synchronized significa manter o bloqueio no object Class da Class onde, como synchronized significa manter o bloqueio no próprio object da class. Isso significa que, se você estiver acessando um método sincronizado não estático em um encadeamento (de execução), ainda poderá acessar um método estático sincronizado usando outro encadeamento.

    Portanto, acessar dois tipos de methods (ou dois methods estáticos ou dois methods não estáticos) em qualquer ponto do tempo por mais de um segmento não é possível.

    Por que você quer impor que apenas um único segmento possa acessar o database a qualquer momento?

    É o trabalho do driver de database para implementar qualquer bloqueio necessário, assumindo que uma Connection é usada apenas por um thread de cada vez!

    Muito provavelmente, o seu database é perfeitamente capaz de lidar com múltiplos accesss paralelos

    Se é algo a ver com os dados em seu database, por que não utilizar o bloqueio de isolamento de database para conseguir?

    Para responder a sua pergunta, sim, sim: seu método synchronized não pode ser executado por mais de um thread de cada vez.