views:

66

answers:

2

usecase example

  • I have a servlet that is receiving login requests.
  • If a login is currently in process OR the user is already logged in, the servlet should abort and inform the caller.

current design

Taking inspiration from database sharding, I plan to use the first character of each userid as a synchronization key.

void login( String userid )
{
  String first = userid.substring(0, 1);
  synchronized( first.intern() )
  {
    // query the cache or database for a session token.
    // if session token exists, throw an exception
  }
}

questions

  1. I understand that using String#intern might overflow the permgen space. In my case, the string being dumped into permgen is a single unicode character. Am I safe in using interned strings this way ?
+1  A: 

To your question: Perm gen should be able to code with 65,536 one character Strings (should only be a few megs).

However:

  • This clearly isn't going to work on multi-process systems.
  • You run the risk of deadlock (if some other code is synchronising on such Strings).
  • It's really ugly.
  • Really you want a proper throttling(!), which shouldn't be at all difficult.
Tom Hawtin - tackline
How would it not work in a multi-processor machine ? Assuming there is only one JVM. If I use my own Locks, how does it differ from using an interned String (in a multi-processor machine)?
Jacques René Mesrine
He did not say this will not work on a multi-processor machine. It will not work on a multi-process system, i.e. a system where you have multiple instances of the JVM running (either on a single computer or on multiple computers) - 'synchronized' does not work across JVMs.
Jesper
Thanks. I thought that was a typo.
Jacques René Mesrine
+1  A: 

The PermGen overflow is not an issue. However:

  1. String.intern() is a heavyweight operation, since it requires locking the String constant pool. This will reduce your throughput;
  2. More importantly, you will synchronise on objects which 'escape' your control, e.g. if a library you use has a

    synchronized ("a") {
       // do stuff
    }
    

block somewhere, you will deadlock without knowing it. It's more or less the same issue as synchronising on Boolean or Integer values. I suggest you use your own locks for this.

Robert Munteanu
Thank you. I'm in the process of migrating my design to use custom locks.
Jacques René Mesrine
`intern` is in a sense heavyweight, but when you are talking about using database connections and the such like, it is relatively tiny.
Tom Hawtin - tackline