2

In Java strings are special.

Since string literals with the same contents share storage in the common pool, Java's String is designed to be immutable. That is, once a String is constructed, its contents cannot be modified. Otherwise, the other String references sharing the same storage location will be affected by the change, which can be unpredictable and therefore is undesirable.

What if I synchronize on a String ? Will I lock across all instances of String sharing the same contents ?

For example : I have a multithreaded class which reads and writes from data files. There is 1 file per day and I want to synchronize read and writes to the same file so as to prevent unpredicatble behaviour. Can I simply synchronize on the filename (String) ?

klonq
  • 3,535
  • 4
  • 36
  • 58
  • 2
    string **literals** with the same contents share storage in the common pool. That means that `"foo" == "foo"`. But that doesn't mean that any string with the same content as "foo" is == to "foo". – JB Nizet Apr 07 '18 at 14:45
  • 1
    Locking on a string would be very error prone. There is zero encapsulation in that approach and it's impossible to enforce that policy for new code. Take advantage of OO principles and make a DailyFile class that actually enforces your locking policy As @Elevate suggested. – jeff Apr 07 '18 at 14:54
  • 1
    why do you think that you need to lock ? Other threads of your application may write/read the same file that which one used during the 1 day processing ? – davidxxx Apr 07 '18 at 14:58

2 Answers2

7

You could intern the string, but it's a bit opaque to the next person who has to maintain the code. I'd suggest you create a File object or a separate Object called fileLock (say) to represent the intention more clearly.

ᴇʟᴇvᴀтᴇ
  • 12,285
  • 4
  • 43
  • 66
  • Yes, I agree but there are complexities with this solution also. A lock object would be required for each file and some sort of controller to index the lock objects. Whereas an interned String already provides this fonctionality with the advantage of garbage collecting Strings which haven't been used recently. – klonq Apr 07 '18 at 14:49
  • 1
    @klonq True, but then you don't need to worry about some other class coming along and trying to lock the same objects for an unrelated reason. Isolating there different components of your application is a good habit to get into. – yshavit Apr 07 '18 at 14:59
  • Also someone else could easily break the application by synchronizing on the same string. – lexicore Apr 07 '18 at 17:17
  • Personally, I'd prioritize making it clear what's going on for future developers (or you in six months' time!). By the way, interned strings are not garbage collected because the string pool has static references to them. So if your garbage profile is crucial to you, an interned string wouldn't be the way to go. – ᴇʟᴇvᴀтᴇ Apr 07 '18 at 18:31
2

You can do it with String.intern():

String fileName = "fileName";
fileName = fileName.intern();
synchronized (fileName) {

}
xingbin
  • 27,410
  • 9
  • 53
  • 103
  • @klonq If you are looking for some kind of file name based lock, this may help. https://stackoverflow.com/questions/5639870/simple-java-name-based-locks – xingbin Apr 07 '18 at 14:51
  • I think that if another thread created before a `"fileName" String` (not literal) , it would have a different reference from the `String` returned by `fileName.intern()` and so the synchronized statement will not lock this other reference. – davidxxx Apr 07 '18 at 14:55
  • In this example you don't actually need to intern as string literal `"fileName"` is interned by default. – lexicore Apr 07 '18 at 17:12
  • @davidxxx If that string which was created before was interned (like `("file" + "Name").intern()`) then it will be the same instance. – lexicore Apr 07 '18 at 17:13
  • @lexicode Sure I agree but it is not because the `intern()` is done at a place that we have the guarantee that that be the case everywhere. It was on the point on which I would stress on. – davidxxx Apr 07 '18 at 17:16
  • @user6690200 the library in the link is probably best suited to what I'm doing – klonq Apr 08 '18 at 15:03