2009-03-05 15 views

Respuesta

34

No, no son seguros para subprocesos, según IBM - Java theory and practice: Are all stateful Web applications broken?. Necesitas sincronizar.

How HttpSession is not thread safe de Java Ranch puede ser útil también.

+3

¡Debe leer los enlaces! ++ – cherouvim

+0

¿Por qué le gustaría sincronizarlos? Hay una sesión por cliente y los clientes tienen un solo subproceso ¿no? – OscarRyz

+1

@Oscar Reyes: un cliente puede emitir muchas solicitudes concurrentes. por ejemplo, CTRL + CLIC (en firefox) como loco en el logotipo de stackoverflow. – cherouvim

4

No. Y ya que usted no desea que el mismo cliente (con la sesión) a hacer peticiones concurrentes, debe serializar estas solicitudes como el AbstractController hace en Spring MVC

+1

Me gustó el ejemplo pero todavía estoy un poco confundido sobre cómo usaría esto para mi aplicación. –

2

En cierto modo, esto depende de su diseño del cliente.

¿Tiene la oportunidad, en su diseño web, de que un solo cliente tenga múltiples solicitudes simultáneas pendientes utilizando la misma sesión HTTP? Esto parece difícil de hacer a menos que vincule una sola sesión HTTP a varios sockets. (aka, AJAX) A menos que lo haga, el acceso HTTP de un cliente determinado será de un solo hilo en lo que respecta al servidor, lo que significa que una sola sesión es efectivamente segura.

La sincronización de sus objetos de sesión hará que la aplicación sea más segura contra cambios futuros que hacen que su aplicación web sea capaz de tener múltiples solicitudes simultáneas, por lo que no es una mala idea. En las implementaciones modernas de Java, la sincronización no tiene el gran costo que anteriormente se asociaba con ella, especialmente cuando la sincronización generalmente no está garantizada. Si su aplicación usa AJAX, lo que implica que espera múltiples solicitudes simultáneas en vuelo a su servidor web, entonces la sincronización es imprescindible.

+0

Estaba pensando en deshabilitar "synchronizeOnSession" para las solicitudes ajax para agilizar las cosas (las solicitudes ajax se ejecutan una tras otra, no en paralelo). Entonces, ¿es un gran no, no? Pensé que es seguro para ajax porque el flujo de trabajo generalmente se controla en el lado de JavaScript de todos modos. – serg

0

La sesión no es segura para subprocesos y no se garantiza que los métodos get no the set sean seguros para subprocesos. En general, en un contenedor de servlets, debe suponerse que se encuentra en un entorno de múltiples hilos y que ninguna herramienta proporcionada es segura.

Esto también se aplica a los objetos que almacena en la sesión. La sesión en sí no manipulará el objeto almacenado, pero puede recuperar el objeto en diferentes hilos e intentar manipularlo. Depende de usted examinar su propio código para ver si las condiciones de carrera son posibles.

El ejemplo de código que publicó es válido, pero el problema puede existir más allá del alcance limitado de su ejemplo. Asegura que no hay condiciones durante la configuración de la sesión, pero no hay nada que impida que otro hilo anule el conjunto. Si el código en su solicitud depende de que el valor permanezca inalterado, aún podría tener problemas.

61

Servlet 2.5 spec:

múltiples servlets ejecutoras solicitud hilos pueden tener acceso activo a la mismo objeto de sesión al mismo tiempo. El contenedor debe garantizar que la manipulación de los datos internos estructuras que representan los atributos de la sesión se realice de manera segura para hilos . El Desarrollador tiene la responsabilidad del acceso de hilos a los objetos de atributo .Esto protegerá la colección de atributos dentro del objeto HttpSession del acceso concurrente , eliminando la oportunidad para que una aplicación cause que la colección se corrompe.

Esto es seguro:

// guaranteed by the spec to be safe 
request.getSession().setAttribute("foo", 1); 

Ésta es no segura:

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); 

Ésta es no garantizado al:

// 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); 
} 

He visto este último enfoque defendido (incluso en los libros J2EE), pero no está garantizado que funcione según la especificación de Servlet. Podría use the session ID to create a mutex, pero debe haber un mejor enfoque.

+0

Significa entender qué significa "El contenedor debe garantizar que la manipulación de las estructuras internas de datos que representan los atributos de sesión se realiza de manera segura para hilos". ¿No significa que se supone que un contenedor como 'tomcat' se asegura de que los métodos getAttribute y setAttribute sean seguros para la ejecución de subprocesos? Además, ¿por qué no se garantiza que el último enfoque funcione? – letronje

+0

@letronje: esto significa que las llamadas individuales a getAttribute/setAttribute deben ser seguras para los hilos, pero no se realizan garantías transaccionales para el servlet. Por lo tanto, el uso simultáneo de la misma sesión puede dar como resultado un estado incoherente a menos que el desarrollador del servlet proteja contra eso. – McDowell

+1

@letronje: el último enfoque requiere que la sesión se sincronice en 'this'. Es decir, tiene una firma como 'public syncrhonized void setAttribute ...' o '... setAttribute (String s, Object o) {synchronized (this) ...'. La especificación no requiere esto. Algunos contenedores de servlets hacen esto, pero no hay garantías: cómo el contenedor protege el estado interno es un detalle de implementación. – McDowell

1

No lo son, pero la mayoría de las veces, sus clientes solo tendrán acceso a ellos con un solo hilo.

Diferentes clientes tendrán diferentes hilos y cada uno tendrá su propia sesión.

Como señala Eddie, una situación en la que puede enfrentar dos subprocesos al acceder a la misma sesión es que dos llamadas ajax intentan modificar el mismo atributo de sesión. De lo contrario, no tendrás problemas.

Cuestiones relacionadas