O thread httpsession é seguro, é definido/obter operações seguras de threads de atributo?
-
03-07-2019 - |
Pergunta
Além disso, o objeto que está sendo definido deve ser seguro para garantir que sabemos o que o estado do objeto armazenado na sessão é conhecido.
Além disso, eu estava lendo na web que alguns sugerem usar:
synchronized(session) {
session.setAttribute("abc", "abc");
}
Esta é uma sugestão válida?
Solução
Não, eles não são seguros para fios, de acordo com a IBM - Teoria e prática Java: Todos os aplicativos da Web com estado estão quebrados?. Você precisa sincronizar.
Como httpssession não é seguro Do Java Ranch também pode ser útil.
Outras dicas
Servlet 2.5 Spec:
Vários servlets que executam threads de solicitação podem ter acesso ativo ao mesmo objeto de sessão ao mesmo tempo. O contêiner deve garantir que a manipulação de estruturas de dados internas que representam os atributos da sessão seja realizada de maneira threadSafe. O desenvolvedor tem a responsabilidade pelo acesso do ThreadSafe aos próprios objetos de atributo. Isso protegerá a coleta de atributos dentro do objeto HTTPSession do acesso simultâneo, eliminando a oportunidade de um aplicativo fazer com que essa coleção seja corrompida.
Isso é seguro:
// guaranteed by the spec to be safe
request.getSession().setAttribute("foo", 1);
Isto é não seguro:
HttpSession session = request.getSession();
Integer n = (Integer) session.getAttribute("foo");
// not thread safe
// another thread might be have got stale value between get and set
session.setAttribute("foo", (n == null) ? 1 : n + 1);
Isto é não garantido para estar seguro:
// no guarantee that same instance will be returned,
// nor that session will lock on "this"
HttpSession session = request.getSession();
synchronized (session) {
Integer n = (Integer) session.getAttribute("foo");
session.setAttribute("foo", (n == null) ? 1 : n + 1);
}
Vi essa última abordagem defendida (incluindo os livros J2EE), mas não é garantido que funcione pela especificação do servlet. Você poderia Use o ID da sessão para criar um mutex, mas deve haver uma abordagem melhor.
Não. E como você não deseja que o mesmo cliente (com sessão) faça solicitações simultâneas, você deve serializar em serializar essas solicitações como o AbstractController faz na primavera MVC
De certa forma, isso depende do design do seu cliente.
Você tem a oportunidade, em seu design da web, para um único cliente ter várias solicitações simultâneas excelentes usando a mesma sessão HTTP? Isso parece difícil de fazer, a menos que você amarre uma única sessão HTTP a vários soquetes. (AKA, Ajax) Com falta de fazer isso, o acesso HTTP de um determinado cliente será um único thread no que diz respeito ao servidor, o que significa que uma única sessão é efetivamente segura.
A sincronização de seus objetos de sessão tornará o aplicativo mais seguro contra mudanças futuras que tornam seu aplicativo da Web capaz de ter várias solicitações simultâneas, para que não seja uma má idéia. Nas implementações modernas de Java, a sincronização não tem o grande custo que estava anteriormente associado a ele, especialmente quando a sincronização geralmente não é contendida. Se o seu aplicativo usar o AJAX, o que implica que você espera várias solicitações simultâneas de voo ao seu servidor da Web, a sincronização é uma obrigação.
Eles não são, mas na maioria das vezes, seus clientes apenas os acessam com um único thread.
Clientes diferentes terão tópicos diferentes e cada um terá sua própria sessão.
Como Eddie aponta, uma situação em que você pode enfrentar dois threads que acessam a mesma sessão são duas chamadas de Ajax estão tentando modificar o mesmo atributo de sessão. Caso contrário, você não terá problemas.
A sessão não é segura para thread e nem os métodos de definição não são garantidos para serem seguros. Em geral, em um contêiner de servlet, você deve assumir que está em um ambiente com vários rosqueados e nenhuma ferramenta fornecida é segura.
Isso também vale para os objetos que você armazena na sessão. A sessão em si não manipulará o objeto armazenado, mas você pode recuperar o objeto em diferentes encadeamentos e tentar manipulá -lo. Cabe a você examinar seu próprio código para ver se as condições de corrida são possíveis.
O exemplo de código que você postou é válido, mas o problema pode existir além do escopo limitado do seu exemplo. Ele garante que não há condições durante a configuração da sessão, mas não há nada que impeça um outro thread para substituir o conjunto. Se o código em sua solicitação depende do valor permanecendo inalterado, você ainda poderá estar com problemas.