synchronizing io operation in java on a string method argument? [duplicate]

Basically, I have a class with 2 methods: one to serialize an object into an XML file and another to read an object from XML. Here is an example of synchronized part from the method that restores an object:

    public T restore(String from) throws Exception {
     // variables declaration
        synchronized (from) {
            try {
                decoder = new XMLDecoder(new BufferedInputStream(
                        new FileInputStream(from)));
                restoredItem = decoder.readObject();
            } catch (Exception e) {
                logger.warning("file not found or smth: " + from);
                throw new Exception(e);
    // try to cast it

A similar approach is taken when serializing an object. Now, when I create a unit test which in turn creates 10 threads with each thread trying to serialize and instantly read either a Boolean or a String it would fail showing that ClassCastExceptions occur. This makes me think that I get serialization wrong (everything's ok in a single-threaded environment). If you've stayed with me down to this point :), here are the 2 issues I need your help on:

  1. does it make sense to synchronize on a string argument passed to method (considering there's a string pool in java)? BTW, I've tried synchronizing on the XMLSerializer class itself with result staying the same.
  2. how do i correctly synchronize io operations on a single file?

Asked by: Edgar357 | Posted: 21-01-2022

Answer 1

1. Yes, it's OK to synchronize on a String, however you'd need to synchronize on the string.intern() in order to always get the same Object

StringBuffer sb = new StringBuffer(); sb.append("a").append("b");
String a = new String(sb.toString());
String b = new String(sb.toString());
a == b; //false
a.equals(b); //true
a.intern() == b.intern(); //true

Since you want to synchronize on the same monitor, you'd want the intern().

2. You'd probably not want to synchronize on a String since it may synchronized on somewhere else, inside your code, in 3rd party or in the JRE. What I'd do, if I wanted to stay with synchronize, is create an ID class (which may hold only String), override equals() and hashcode() to match, put it in a WeakHashMap with both as key and value (see IdentityHashMap for idea why) and use only what I .get() from the map (sync map{ syncKey = map.get(new ID(from)); if syncKey==null create and put new key} sync{syncKey}).

3. Then again, I'd ditch synchronize all together and use the java.util.concurrent.locks.Lock instead, in the same setup as above only with the lock attached to the ID.

Answered by: Arthur446 | Posted: 22-02-2022

Answer 2

Given that the some parts of your code are missing, my bet is that the problem lies with synchronizing on a string. You cannot freely assume that strings are pooled (which would break your synchronization scheme).

The best approach would be to add a map that will associate a key (string) with its actual synchronization object.

Other than that, I would suggest to play with the multi-threaded test to see what make it fail. For example, if you make all threads only store string values (rather than strings or beooleans), does the test still fail?

Answered by: Alina400 | Posted: 22-02-2022

Answer 3

There are a number of problems with this approach.

  1. Unless you've called String.intern then your from string is probably not the same from as the other one you are calling. Relying on the behaviour of the internal java string cache is not very robust.

  2. you aren't properly disposing of your XMLDecoder in a finally block, any exception thrown during that call will leak the file description associated with that FileInputStream.

  3. You don't need to wrap e in another Exception(e), you can just throw e as you have declared the enclosing method also throws Exception

  4. Catching/Throwing exception is a code smell. Yes, it is a super class of IOException, and whatever XML decoding exception might be thrown, but its also a superclass of a bunch of other things you probably didn't want to catch, NullPointerException for instance.

To answer your question, how can you serialize access to a shared file to ensure its not being used by more than one thread, is tricky. FileChannel.lock() doesn't work inside the JVM, they just lock the file from modification by other processes in the machine.

My approach would be to strip any locking out of this class and wrap it in something that is aware of the threading issues of your code.

I'd also not pass a String as the filename, but a File, which gives you the ability to use File.createTempFile(2) to create opaque filenames between the thing writing xml and the thing reading xml.

Finally, do you want to synchronise access to a shared file, or fail when you detect multiple access to the same file?

Answered by: Julia218 | Posted: 22-02-2022

Answer 4

A String does not good make a good mutex, but can be used to create one: Java: synchronizing on an ID.

Answered by: Kimberly910 | Posted: 22-02-2022

Similar questions

multithreading - Java: synchronizing threads across multiple servers

I have a problem where I need to synchronize processing for multiple threads across multiple different servers for a Java service on Windows. In this application, I have multiple consumer threads pullings messages off the same JMS queue. Messages come in in groups of 3 or 4, and I need to make sure the messages in each group are processed completely in serial. I need some sort of synch mechanism to make sure if t...

multithreading - Java concurrency question - synchronizing on a collection

Will the following code snippet of a synchronized ArrayList work in a multi-threaded environment? class MyList { private final ArrayList<String> internalList = new ArrayList<String>(); void add(String newValue) { synchronized (internalList) { internalList.add(newValue); } } boolean find(String match) { synchronized (internalList)...

multithreading - Synchronizing several threads writing to the same file in java

Of course there is the obvious way of using "synchronized". But I'm creating a system designed for running on several cores and writing to that file various times at the same milisecond. So I believe that using synchronize will hurt performance badly. I was thinking of using the Pipe class of java (but not sure if it will help) or having each thread write to a different file and an additional thread collecting those writin...

multithreading - Java synchronizing static list?

In a Java class , i am having a static list so this list is shared across all the objects of this class.The business logic in this class will run periodically which is invoked by some method with out passing instance parameters.Now I want to invoke this run method based on the list(I will add some vales into this list based on JMS) ,this list may empty sometimes and after finishing the run , i am emptying this list.Now my ...

multithreading - synchronizing thread in java

I am implementing java Runnable interface for multithreading. I have some n number of threads. Each of the thread has its own life. I would like to wait till life of all the threads get expire. Lets say following is the case for(int i = 0; i< k;i++){ Thread thread1 = new Thread(new xyz()) Thread thread2 = new Thread(new abc()) Thread thread3 = new Thread(new mno()) thread1....

multithreading - Java - synchronizing multiple threads on time-step basis

Suppose I have a Master that keeps a list of SlaveThread objects. On each time step, I want the Master to run the SlaveThreads in parallel, however, at the end of the time step, I want the SlaveThreads to to wait for each other to complete the current time step before advancing forward. Also, I don't want to reinstantiate the SlaveThreads on each time step. I have 2 possible solutions, and I don't know how to make either o...

multithreading - Best way of synchronizing lots of threads in java

I develop an application, and, at a given moment, I start about 10000 threads to stress-test a database. I want to synchronize this in the following way: I want to read all data from a table in all the threads, then I want all the treads to wait for the other threads to stop reading. After all threads finished reading, I delete all records from that table, then I want all the threads to insert the data read previously. Now...

multithreading - Java - synchronizing getSize() on List

List<Ball> myObjs = myThreads[threadIndex].getMyObjList(); int initialSize = Collections.synchronizedList(myObjs).size(); Throws ConcurrentModificationException. I have also tried putting this in a synchronized(myObjs) block, but it also didn't work. What is the solution? Everywhere else where I use this list, it is in an synchronized(block). P.S. This error also ends up producing Br...

multithreading - Java synchronizing based on a parameter (named mutex/lock)

I'm looking for a way to synchronize a method based on the parameter it receives, something like this: public synchronized void doSomething(name){ //some code } I want the method doSomething to be synchronized based on the name parameter like this: Thread 1: doSomething("a"); Thread 2: doSomething("b"); Thread 3: doSomething("c"); T...

multithreading - Java concurrent programming - synchronizing array

Let's say I have four classes: Party, Creature, Job, Item. Parties have creatures Parties have items Creatures have jobs (Threads) Jobs require items I am having trouble determining how to synchronize the individual items, such that no job can access an item at the same time. I assembled a list of all the items available in the party in the form ArrayList<ItemInstance>

multithreading - Java BlockingQueue of Size=1?

Essentially what I want is a BlockingQueue of size=1. I have a "listener" thread that simply waits, blocking until an object is put into the queue, and then retrieves it--and a "producer" thread that actually puts the object into the queue. I can implement this with some synchronized blocks and a BlockingQueue implementation, but that seems like overkill. Is there a better, simpler way to do what I want? Ex...

multithreading - HTTP posts and multiple threads in Java

I am writing an internal Java Applet to do file uploads via HTTP. I started using the built in ClientHttpRequest which worked great if I want to post one after another. When I try to have multiple threads post at the same time, something on the server side freaks out and the connection will hang for large files while still uploading the smaller files. (Large seems to be around 10 megs) After lots of looking, I would no...

multithreading - Tools for finding Shared Mutable data bugs in Java

I have a large legacy system to maintain. The codebase uses threads all over the place and those threads share a lot of mutable data. I know, sounds bad. Anyway, don't answer "rewrite the whole application from scratch" or I'll vote you down :-) I have tried to run some static analysis tools on the codebase, but none of those seem to catch this case which occurs a lot in our source code: multiple threads are reading and wr...

multithreading - Stopping a Thread in Java?

This question already has answers here:

multithreading - Threading issues in a Java HashMap

Something happened that I'm not sure should be possible. Obviously it is, because I've seen it, but I need to find the root cause & I was hoping you all could help. We have a system that looks up latitude & longitude for a zipcode. Rather than access it every time, we cache the results in a cheap in-memory HashTable cache, since the lat & long of a zip code tend to change less often than we release.

multithreading - Firing a mainline event from a background thread in Java

My question pertains to multi-threading in Java. I'm translating an app I wrote in Visual Basic 2008 into Java. There is a class in VB called BackgroundWorker, which allows the coder to perform a task on another thread, a lot like SwingWorker in Java. The only distinct difference ...

multithreading - Java: Run a Callable in a separate process

Given an instance x of Callable<T>, how can I run x in a separate process such that I can redirect the standard input and output of the process? For example, is there a way to build a Process from a Callable? Is there a standard Executor that gives control over input and output? [UPDATE] It's not important that the Callable

multithreading - How can you ensure in java that a block of code can not be interrupted by any other thread

exampl: new Thread(new Runnable() { public void run() { while(condition) { *code that must not be interrupted* *some more code* } } }).start(); SomeOtherThread.start(); YetAntherThread.start(); How can you ensure that code that must not be interrupted won't be interrupted?

multithreading - Java while loop and Threads!

This question already has answers here:

multithreading - In Java critical sections, what should I synchronize on?

In Java, the idiomatic way to declare critical sections in the code is the following: private void doSomething() { // thread-safe code synchronized(this) { // thread-unsafe code } // thread-safe code } Almost all blocks synchronize on this, but is there a particular reason for this? Are there other possibilities? Are there any best practices on what object to sync...

Still can't find your answer? Check out these amazing Java communities for help...

Java Reddit Community | Java Help Reddit Community | Java Community | Java Discord | Java Programmers (Facebook) | Java developers (Facebook)