The problem is that different requests (from different browsers on the same machine, or different machines) are handled by the container as different THREADS acting upon a single INSTANCE of the servlet.
So, these different threads could concurrently access the session, and you could get results that you weren't expecting.
Synchronizing on the session means that whenever a thread wants to access the session, it must first access the session object's lock. There is only a single lock, so only one thread can access the session at once. This protects the session (and you) from getting results you weren't expecting from threads concurrently accessing the session.
The downside of course, is that while one thread has the lock, all other threads are blocked, so synchronizing for long periods of time could be bad for performance. I think HFSJ gives the advice to "get in, do whatever you need and get out".