0

use case 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 ?
BenMorel
  • 34,448
  • 50
  • 182
  • 322
Jacques René Mesrine
  • 46,127
  • 27
  • 66
  • 104

2 Answers2

1

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
  • 145,806
  • 30
  • 211
  • 305
  • 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 Aug 31 '09 at 08:43
  • 1
    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 Aug 31 '09 at 12:12
  • Thanks. I thought that was a typo. – Jacques René Mesrine Aug 31 '09 at 13:37
1

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
  • 67,031
  • 36
  • 206
  • 278