January 25, 2011

QCJSON Now Thread Safe

Posted in Android Development, misc tagged , , , , , , , , , , , , at 7:25 am by tetontech

The changes described here are found in QCJSON v. 1.0.2 available on sourceForge .  The license is BSD.  You can get the source code from the git repository on sourceForge using the command:

git clone git://qcjson.git.sourceforge.net/gitroot/qcjson/qcjson

or look at it online.

I’ve been pondering how to make QCJSON thread safe meaning that you could read and write to the same stream from separate threads safely without impacting any other streams that may be being used in the same or other threads.

The problem description is that you don’t want to start a read when one is part way complete.  Nor do you want to start a write in the middle of another write.  Both of these situations plus mixing read and write can cause serious data corruption.

I briefly played with the idea of creating a Class that would contain a static semaphore.  This static semaphore would control access to the reading and writing behavior of the existing code.  The problem is that with this approach reading or writing to one stream on one thread would cause any other threads to wait at the semaphore claim location even if the stream that it wished to write to was in no way associated with the stream that was currently being used.  In other words reading or writing on one stream would block reading and writing on all streams until it was complete.  Obviously this is an unacceptable solution.  You might as well just write in one thread.

Since there is no way of interrogating an input our output stream object in Java it isn’t possible to hide the threading locks from the programmer using the QCJSON library and allow independent streams to work in independent threads.

While I’ve thought through several options the one that seems the best is to allow you, the developer, to pair input and output streams and include a semaphore in this pairing.  This is going to require a new class.

For lack of a better name I am calling this new class org.quickconnect.json.JSONStreamProtector.  It has a default constructor that takes no parameters and has one public method, protectJSONStream(JSONStream aStream).

If you instantiate a JSONStreamProtector you can pass the protectJSONStream method any number of JSONInputStreams and JSONOutputStreams.  Any streams that you pass as a parameter to this method will share the same semaphore.  Thus when you call readObject or writeObject on the protected streams any threads that would be using these streams will block in their readObject or writeObject methods until it is safe to proceed.

Using JSONStreamProtector

Changes have been made in the JSONInputStream and JSONOutputStream classes so that  if a protector has been set for them the stream will claim or wait until it is able to claim the semaphore in its defined protector.

You needn’t put the protector in a collection or some other class’ attributes in order for it to not be garbage collected.  Passing one JSONStream to the protectJSONStream method is sufficient.

In Example 1 the code shows how to protect a single output stream from three separate threads trying to write to the stream simultaneously.  Input streams work the same way.  Protecting an input/output stream pair that work on the same underlying resource would just mean using the same protector for both streams.

Any stream can only have one protector at a time.  This keeps your code from accidentally getting in a cross-locking situation.  You can switch the protector is is using at any time by calling the new protectors’ protectJSONStream method.

Example 1:

try {
/*
* Add three output streams to the same file and then have each of them send
* json to the stream. Make sure that no data corruption occurs.
*/
JSONStreamProtector aProtector = new JSONStreamProtector();
FileOutputStream testOut = new FileOutputStream(aFile);
/*
* stuff to write to file
*/
int[] testIntArray = {7,10,0,-789};
String[] testStringArray = {"What","is","happening?"};
TestObject anObject = new TestObject("Hello there.", 7, new Date(1067899));

 

/*
* do the running
*/
JSONOutputStream jsonTestOut1 = new JSONOutputStream(testOut);
aProtector.protectJSONStream(jsonTestOut1);

Thread testThread1 = new Thread(new ProtectorTestWriteRunnable(jsonTestOut1, testIntArray));

JSONOutputStream jsonTestOut2 = new JSONOutputStream(testOut);
aProtector.protectJSONStream(jsonTestOut2);

Thread testThread2 = new Thread(new ProtectorTestWriteRunnable(jsonTestOut1, testStringArray));

JSONOutputStream jsonTestOut3 = new JSONOutputStream(testOut);
aProtector.protectJSONStream(jsonTestOut3);

Thread testThread3 = new Thread(new ProtectorTestWriteRunnable(jsonTestOut1, anObject));
testThread1.start();
testThread2.start();
testThread3.start();

 

} catch (Exception e) {
e.printStackTrace();
}

 

The source code for the protector class is simple so I’ll just put it here.


package org.quickconnect.json;

import java.util.concurrent.Semaphore;

public class JSONStreamProtector{
private Semaphore semaphore = new Semaphore(1, true);
public void protectJSONStream(JSONStream aJsonStream){

aJsonStream.setProtector(this);

}
protected void claim() throws InterruptedException{
semaphore.acquire(1);
}
protected void free(){
semaphore.release(1);
}
}

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: