Thread A Thread B | | session.invalidate() | | | +- StandardSession#invalidate() | | | +- StandardSession#expire() | | | +- StandardSession#expire(true) | | | if (expiring || !isValid) { } --> false | | | synchronized(this) { | | | ... | | | expiring = true; | | | ... (many things happening) session.invalidate() | | | +- StandardSession#invalidate() | | | StandardSession#expire() | | | +- StandardSession#expire(true) | | | if (expiring || !isValid) return; --> true | | | +-----+ | | | session = request.getSession(true) | | | +- ApplicationHttpRequest#getSession(true) | | | if (crossContext) { --> true | | | ... | | | if (session != null && session.isValid()) { --> true | | | return (session.getSession()); | | | } | | | } | | | +--+ | | | | // now session refers to the same object as befor an object in state "expiring" setValid(false) | | | ... | | | expiring = false; | | | } // end of synchronization block | | | // now session refers to an invalidated object +--------+ |