Instantiating with a Pool<T> class via PoolObjectFactory interface - java

Here is an example of using Java Pool (pool of generics) in order to instantiate TouchEvents for Android:
import java.util.ArrayList;
import java.util.List;
public class Pool<T> {
public interface PoolObjectFactory<T> {
public T createObject();
}
private final List<T> freeObjects;
private final PoolObjectFactory<T> factory;
private final int maxSize;
public Pool(PoolObjectFactory<T> factory, int maxSize) {
this.factory = factory;
this.maxSize = maxSize;
this.freeObjects = new ArrayList<T>(maxSize);
}
public T newObject() {
T object = null;
if (freeObjects.isEmpty()) {
object = factory.createObject();
} else {
object = freeObjects.remove(freeObjects.size() - 1);
}
return object;
}
public void free(T object) {
if (freeObjects.size() < maxSize) {
freeObjects.add(object);
}
}
}
However, I don't really understand how this code works:
if (freeObjects.isEmpty()) {
object = factory.createObject();
} else {
object = freeObjects.remove(freeObjects.size() - 1);
}
Lets say we have:
touchEventPool = new Pool<TouchEvent>(factory, 100);
Does this mean it is going to store an Array of 100 events (and when #101 comes inside, will dispose #1, like first-in-first-out)?
I assume it supposed to hold some maximum number of objects and then dispose the extra. I read book's description like 10 times.. and couldn't get it. Maybe someone explain how this works?

I assume it supposed to hold some maximum number of objects and then dispose the extra. I read book's description like 10 times.. and couldn't get it. Maybe someone explain how this works?
Sort of. The class keeps a cache of pre-created objects in a List called pool. When you ask for a new object (via the newObject method) it will first check the pool to see if an object is available for use. If the pool is empty, it just creates an object and returns it to you. If there is an object available, it removes the last element in the pool and returns it to you.
Annotated:
if (freeObjects.isEmpty()) {
// The pool is empty, create a new object.
object = factory.createObject();
} else {
// The pool is non-empty, retrieve an object from the pool and return it.
object = freeObjects.remove(freeObjects.size() - 1);
}
And when you return an object to the cache (via the free() method), it will only be placed back into the pool if the maximum size of the pool has not been met.
Annotated:
public void free(T object) {
// If the pool is not already at its maximum size.
if (freeObjects.size() < maxSize) {
// Then put the object into the pool.
freeObjects.add(object);
}
// Otherwise, just ignore this call and let the object go out of scope.
}
If the pool's max size has already been reached, the object you are freeing is not stored and is (presumably) subject to garbage collection.

The idea of any pool is in creating controlled environment where (usually) no need to create new (event) instances when some unused free instances can be re-used from the pool.
When you create
touchEventPool = new Pool<TouchEvent>(factory, 100);
you hope 100 instances will be enough in any particular moment of the program live.
So when you want to get 101'st event the process probably will free first 5, 20 or even 99 events and the pool will be able to reuse any of them.
If there will be no free instances then depending on the pool policy the new one will be created or the requestor thread will wait other threads to release one and return to the pool. In this particular implementation the new one will be created.

I think that the main concept of object pool is to reduce frequency of object instanciations.
Does this mean it is going to store an Array of 100 events (and when #101 comes inside, will dispose #1, like first-in-first-out)?Does this mean it is going to store an Array of 100 events (and when #101 comes inside, will dispose #1, like first-in-first-out)?
I don't think so. The maximum number 100 means that of freeObjects but of currently using objects. When an object is not used any more, you shall free it. Then the freed object won't be descarded but be stocked as a freeObject (the max num means that of these spared objects). Next time you need another new object, you don't have to instanciate a new object. All you need is just reusing one of spared freeObjects.
Thus you can avoid costly object instanciations. It can improve in performance.

Related

Does Runnable share the data structure if they are getting changed?

I am creating a Runnable in the following way:
public class AbcRunnable implements Runnable
{
Qwe qwe;
Rst rst;
public void run() {
// some operations on qwe and rst which are changing their value
}
}
public class AbcThreadPool {
private final AbcThreadPoolExecutor executor;
public InventoryAvailabilityThreadPool(final AbcRunnableFactory factory,
final Integer poolSize) {
executor = new AbcThreadPoolExecutor(factory, poolSize);
for (int i = 0; i < poolSize; ++i) {
executor.execute(factory.get());
}
}
private static class AbcThreadPoolExecutor extends ThreadPoolExecutor {
private final AbcRunnableFactory factory;
public AbcThreadPoolExecutor(final AbcRunnableFactory factory,
final int poolSize) {
super(poolSize, poolSize, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
this.factory = factory;
allowCoreThreadTimeOut(false);
}
}
}
public class AbcRunnableFactory {
#Override
public AbcRunnable get() {
return new AbcRunnable();
}
}
Initialization of Qwe and Rst is being done by the guice module, say, as follows:
#Provides
#Singleton
private AbcRunnableFactory provideAbcRunnableFactory() {
return new AbcRunnableFactory(
new Qwe(), new Rst());
}
So, here AbcRunnable has 2 variables: qwe and rst. My question here is, do different Runnables have their own variables or are they getting shared? Please help in explaining this.
I am very confused when trying to understand what is thread safe or not. So, this may be a very naive question.
Each new instance of AbcRunnable will have its own set of fields (list1 and map1). Since your loop is calling factory.get() in each iteration, and that creates a new AbcRunnable, each thread pool task will have a unique instance of the runnable and its contained fields.
Now, you haven't showed how you initialize the fields inside AbcRunnable:
If you create new List and Map instances in the constructor, then nothing is shared between threads and your code is thread-safe.
If you are passing in any of these values from the outside, then your different AbcRunnable instances could potentially share references to the same list/map and you will need to ensure synchronized access to the data (or use a concurrent collection implementation, which is already thread-safe).
The answer depends how you instantiate your runables. There is a lot going on here so let's simplify. Say we have a very large set of n numbers we want to sum. We can split the set in two and create 2 threads, when they return we just sum the two results. Because we could divide the set in two and sum at the end there is nothing shared, everything is thread safe.
Now let's say we want to know how many of our n numbers have been summed as they are working. We need a shared counter that each thread can increment as the two threads sum. So if the counter is 100 and both threads try to increment it at the same time, both threads will read 100 add 1 and return 101 to memory, the new count will be 101 but really 102 numbers have been summed. For shared variables like our counter we need to make sure only one thread at a time has access at a time if they are writing to it.
In your case if you send the same list or map to two threads you would have a problem because lists and maps are passed by reference or the address in memory is what is sent to the new thread so both might try to modify them at the same time. However, if you split your list and map into distinct values before sending it then you should be fine.

My Java app running out of memory

My application is running out of memory while performing an operation with a large data. The data is a Java List and is around 100K elements in size.
PersistData is the class which implements the operation and PersistDataIntoDB is the class which does the actual operation. Because the operation time consuming, the caller to PersistData gets a response saying the operation is started and there are additional APIs to get the status of the operation.
Also, the entire operation in concurrent and there are multiple callers to the operation.
Here is what the code looks like (I hope its readable).
public class PersistData {
public Boolean persistData(List<ClassA> dataRecs) {
//some checks (smaller operation)
persistDataInDifferentThread(dataRecs);
//if no errors in checks return true
return true;
}
private void persistDataInDifferentThread(List<ClassA> dataRecs) {
Thread runnerThread = new Thread(new Runnable() {
public void run() {
try {
List convertedList = constructClassBUsingClassA(dataRecs);
PersistDataIntoDB dbPersist = new PersistDataIntoDB();
dbPersist.persistDataInDB(convertedList);
}
catch (Exception e) {
}
}
});
}
private List<ClassB> constructClassBUsingClassA(List<ClassA> dataRecs) {
List<ClassB> tempList = new ArrayList<ClassB>();
for (int i = 0; i < dataRecs.size(); i++) {
ClassA tempRec = dataRecs.get(i);
ClassB tempRecB = new ClassB();
//put stuff from tempRec to tempRecB
tempList.add(tempRecB);
}
return tempList;
}
}
Class which does the persistance.
public class PersistDataIntoDB {
public Boolean persistDataInDB(List<ClassB> dataRecs){
//if all goes well return true
return true;
}
}
My question is if my method persistDataInDifferentThread can be refactored ?because while it is running, there are two large Lists in memory and the call to persistDataInDB take long time to finish and the garbage collector may not be unloading the List<ClassA> even though I don’t need it after calling persistDataInDB.
Is my above analysis wrong? I just have to increase the max heap because I am dealing with large data?
Is my above analysis wrong? I just have to increase the max heap because I am dealing with large data?
Yes, and yes.
1) Using multiple threads does not increase or reduce the amount of heap space used.
2) If the heap fills up, then the JVM will make every effort to reclaim space before throwing an OOME.
The only thing that might make a difference is if one thread creates the list and passes it to the second instance to be persisted ... and also hangs onto a reference to the list. That might cause the list to remain reachable longer than it needs to be.
I guess you could also get into trouble if you have multiple runner threads persisting multiple lists, and the work is arriving faster than you can process it. If that is the problem, then you need to do something to control the rate at which you accept the requests.

Java, what is the purpose of Partially Initialised Object exploitation

I am doing some personal research for examinations. Past exams have asked Outline how a partially initialised object in Java is vulnerable to exploitation. and also, What are the possible complications of somebody exploiting said Objects in your application
Now, i found this resource here: securecoding.cert
On the above website, i can see examples as to how its done, but i can't seem to see or understand the purpose of it, what can you actually maliciously do with such Objects.
From what i understand, you should always check that Object instantiation has completed when performing operations (e.g. Boolean or similar) like so;
class BankAccount {
private int balance; // Defaults to 0
private volatile boolean initialized = false;
public BankAccount() {
if (!performAccountVerification()) {
throw new SecurityException("Invalid Account");
}
balance = 1000;
// ...
initialized = true;
}
public int getBalance() {
if (!initialized) {
throw new IllegalStateException("Class not initialized");
}
return balance;
}
// ...
}
Code taken from the above resource.
You should also use volatile, as you want to ensure synchronisation because part of the problem is the fact that the Java Memory allows other Threads to access these Partially Initialised Objects.
So in summary:
Why would you want to do this?
What can you actually do with these Objects
Should you always be concerned about this, or only in critical systems?
Thanks,
Chris.
Well, if I don't have access to a bank account, and your class isn't checking that initialized flag, I could theoretically be able to do something like this:
class Thief extends Thread {
public BankAccount ba = null;
void run() {
do {
if(ba != null) ba.transferAllMoneyToDima();
} while(ba == null);
}
}
Thief th = new Thief();
th.start();
th.ba = new BankAccount();
What happens here is that BankAccount constructor is supposed to verify that I have access to the account, and throw an exception if not. By optimizer is allowed to reorder certain operations. In particular, it can assign the object to th.ba immediately after it is allocated, before the constructor completes. If that happens, my Thief thread will see the non-null value, and steal of the money before the vertification completes and determines that I should not have been allowed to do this.

"Atomically" update an entire array

I have a single writer thread and single reader thread to update and process a pool of arrays(references stored in map). The ratio of writes to read is almost 5:1(latency of writes is a concern).
The writer thread needs to update few elements of an array in the pool based on some events. The entire write operation(all elements) needs to be atomic.
I want to ensure that reader thread reads the previous updated array if writer thread is updating it(something like volatile but on entire array rather than individual fields). Basically, I can afford to read stale values but not block.
Also, since the writes are so frequent, it would be really expensive to create new objects or lock the entire array while read/write.
Is there a more efficient data structure that could be used or use cheaper locks ?
How about this idea: The writer thread does not mutate the array. It simply queues the updates.
The reader thread, whenever it enters a read session that requires a stable snapshot of the array, applies the queued updates to the array, then reads the array.
class Update
{
int position;
Object value;
}
ArrayBlockingQueue<Update> updates = new ArrayBlockingQueue<>(Integer.MAX_VALUE);
void write()
{
updates.put(new Update(...));
}
Object[] read()
{
Update update;
while((update=updates.poll())!=null)
array[update.position] = update.value;
return array;
}
Is there a more efficient data structure?
Yes, absolutely! They're called persistent data structures. They are able to represent a new version of a vector/map/etc merely by storing the differences with respect to a previous version. All versions are immutable, which makes them appropiate for concurrency (writers don't interfere/block readers, and vice versa).
In order to express change, one stores references to a persistent data structure in a reference type such as AtomicReference, and changes what those references point to - not the structures themselves.
Clojure provides a top-notch implementation of persistent data structures. They're written in pure, efficient Java.
The following program exposes how one would approach your described problem using persistent data structures.
import clojure.lang.IPersistentVector;
import clojure.lang.PersistentVector;
public class AtomicArrayUpdates {
public static Map<Integer, AtomicReference<IPersistentVector>> pool
= new HashMap<>();
public static Random rnd = new Random();
public static final int SIZE = 60000;
// For simulating the reads/writes ratio
public static final int SLEEP_TIMÉ = 5;
static {
for (int i = 0; i < SIZE; i++) {
pool.put(i, new AtomicReference(PersistentVector.EMPTY));
}
}
public static class Writer implements Runnable {
#Override public void run() {
while (true) {
try {
Thread.sleep(SLEEP_TIMÉ);
} catch (InterruptedException e) {}
int index = rnd.nextInt(SIZE);
IPersistentVector vec = pool.get(index).get();
// note how we repeatedly assign vec to a new value
// cons() means "append a value".
vec = vec.cons(rnd.nextInt(SIZE + 1));
// assocN(): "update" at index 0
vec = vec.assocN(0, 42);
// appended values are nonsense, just an example!
vec = vec.cons(rnd.nextInt(SIZE + 1));
pool.get(index).set(vec);
}
}
}
public static class Reader implements Runnable {
#Override public void run() {
while (true) {
try {
Thread.sleep(SLEEP_TIMÉ * 5);
} catch (InterruptedException e) {}
IPersistentVector vec = pool.get(rnd.nextInt(SIZE)).get();
// Now you can do whatever you want with vec.
// nothing can mutate it, and reading it doesn't block writers!
}
}
}
public static void main(String[] args) {
new Thread(new Writer()).start();
new Thread(new Reader()).start();
}
}
Another idea, given that the array contains only 20 doubles.
Have two arrays, one for write, one for read.
Reader locks the read array during read.
read()
lock();
read stuff
unlock();
Writer first modifies the write array, then tryLock the read array, if locking fails, fine, write() returns; if locking succeeds, copy the write array to the read array, then release the lock.
write()
update write array
if tryLock()
copy write array to read array
unlock()
Reader can be blocked, but only for the time it takes to copy the 20 doubles, which is short.
Reader should use spin lock, like do{}while(tryLock()==false); to avoid being suspended.
I would do as follows:
synchronize the whole thing and see if the performance is good enough. Considering you only have one writer thread and one reader thread, contention will be low and this could work well enough
private final Map<Key, double[]> map = new HashMap<> ();
public synchronized void write(Key key, double value, int index) {
double[] array = map.get(key);
array[index] = value;
}
public synchronized double[] read(Key key) {
return map.get(key);
}
if it is too slow, I would have the writer make a copy of the array, change some values and put the new array back to the map. Note that array copies are very fast - typically, a 20 items array would most likely take less than 100 nanoseconds
//If all the keys and arrays are constructed before the writer/reader threads
//start, no need for a ConcurrentMap - otherwise use a ConcurrentMap
private final Map<Key, AtomicReference<double[]>> map = new HashMap<> ();
public void write(Key key, double value, int index) {
AtomicReference<double[]> ref = map.get(key);
double[] oldArray = ref.get();
double[] newArray = oldArray.clone();
newArray[index] = value;
//you might want to check the return value to see if it worked
//or you might just skip the update if another writes was performed
//in the meantime
ref.compareAndSet(oldArray, newArray);
}
public double[] read(Key key) {
return map.get(key).get(); //check for null
}
since the writes are so frequent, it would be really expensive to create new objects or lock the entire array while read/write.
How frequent? Unless there are hundreds of them every millisecond you should be fine.
Also note that:
object creation is fairly cheap in Java (think around 10 CPU cycles = a few nanoseconds)
garbage collection of short lived object is generally free (as long as the object stays in the young generation, if it is unreachable it is not visited by the GC)
whereas long lived objects have a GC performance impact because they need to be copied across to the old generation
The following variation is inspired by both my previous answer and one of zhong.j.yu's.
Writers don't interfere/block readers and vice versa, and there are no thread safety/visibility issues, or delicate reasoning going on.
public class V2 {
static Map<Integer, AtomicReference<Double[]>> commited = new HashMap<>();
static Random rnd = new Random();
static class Writer {
private Map<Integer, Double[]> writeable = new HashMap<>();
void write() {
int i = rnd.nextInt(writeable.size());
// manipulate writeable.get(i)...
commited.get(i).set(writeable.get(i).clone());
}
}
static class Reader{
void read() {
double[] arr = commited.get(rnd.nextInt(commited.size())).get();
// do something useful with arr...
}
}
}
You need two static references: readArray and writeArray and a simple mutex to track when write has been changed.
have a locked function called changeWriteArray make changes to a deepCopy of writeArray:
synchronized String[] changeWriteArray(String[] writeArrayCopy, other params go here){
// here make changes to deepCopy of writeArray
//then return deepCopy
return writeArrayCopy;
}
Notice that changeWriteArray is functional programming with effectively no side effect since it is returning a copy that is neither readArray nor writeArray.
whoever calles changeWriteArray must call it as writeArray = changeWriteArray(writeArray.deepCopy()).
the mutex is changed by both changeWriteArray and updateReadArray but is only checked by updateReadArray. If the mutex is set, updateReadArray will simply point the reference of readArray to the actual block of writeArray
EDIT:
#vemv concerning the answer you mentioned. While the ideas are the same, the difference is significant: the two static references are static so that no time is spent actually copying the changes into the readArray; rather the pointer of readArray is moved to point to writeArray. Effectively we are swapping by means of a tmp array that changeWriteArray generates as necessary. Also the locking here is minimal as reading does not require locking in the sense that you can have more than one reader at any given time.
In fact, with this approach, you can keep a count of concurrent readers and check the counter to be zero for when to update readArray with writeArray; again, furthering that reading requires no lock at all.
Improving on #zhong.j.yu's answer, it is really a good idea to queue the writes instead of trying to perform them when they occur. However, we must tackle the problem when updates are coming so fast that the reader would choke on updates continuously coming in. My idea is what if the reades only performs the writes that were queued before the read, and ignoring subsequent writes (those would be tackled by next read).
You will need to write your own synchornised queue. It will be based off a linked list, and would contain only two methods:
public synchronised enqeue(Write write);
This method will atomically enqueue a write. There is a possible deadlock when writes would come faster than it would actually take to enqueue them, but I think there would have to be hundreds of thousands of writes every second to achieve that.
public synchronised Element cut();
This will atomically empty the queue and returns its head (or tail) as the Element object. It will contain a chain of other Elements (Element.next, etc..., just the usual linked list stuff), all those representing a chain of writes since last read. The queue would then be empty, ready to accept new writes. The reader then can trace the Element chain (which will be standalone by then, untouched by subsequent writes), perform the writes, and finally perform the read. While the reader processes the read, new writes would be enqueued in the queue, but those will be next read's problem.
I wrote this once, albeit in C++, to represent a sound data buffer. There were more writes (driver sends more data), than reads (some mathematical stuff over the data), while the writes had to finish as soon as possible. (The data came in real-time, so I needed to save them before next batch was ready in the driver.)
I've got a funny solution using three arrays and a volatile boolean toggle. Basically, both threads have its own array. Additionally, there's a shared array controlled via the toggle.
When the writer finishes and the toggle allows it, it copies the newly written array into the shared array and flips the toggle.
Similarly, before the reader starts, when the toggle allows it, it copies the shared array into its own array and flips the toggle.
public class MolecularArray {
private final double[] writeArray;
private final double[] sharedArray;
private final double[] readArray;
private volatile boolean writerOwnsShared;
MolecularArray(int length) {
writeArray = new double[length];
sharedArray = new double[length];
readArray = new double[length];
}
void read(Consumer<double[]> reader) {
if (!writerOwnsShared) {
copyFromTo(sharedArray, readArray);
writerOwnsShared = true;
}
reader.accept(readArray);
}
void write(Consumer<double[]> writer) {
writer.accept(writeArray);
if (writerOwnsShared) {
copyFromTo(writeArray, sharedArray);
writerOwnsShared = false;
}
}
private void copyFromTo(double[] from, double[] to) {
System.arraycopy(from, 0, to, 0, from.length);
}
}
It depends on the "single writer thread and single reader" assumption.
It never blocks.
It uses a constant (albeit huge) amount of memory.
Repeated calls to read without any intervening write do no copying and vice versa.
The reader does not necessarily see the most recent data, but it sees the data from the first write started after the previous read, if any.
I guess, this could be improved using two shared arrays.

How do I create a thread-safe write-once read-many value in Java?

This is a problem I encounter frequently in working with more complex systems and which I have never figured out a good way to solve. It usually involves variations on the theme of a shared object whose construction and initialization are necessarily two distinct steps. This is generally because of architectural requirements, similar to applets, so answers that suggest I consolidate construction and initialization are not useful. The systems have to target Java 4 at the latest, so answers that suggest support available only in later JVMs are not useful either.
By way of example, let's say I have a class that is structured to fit into an application framework like so:
public class MyClass
{
private /*ideally-final*/ SomeObject someObject;
MyClass() {
someObject=null;
}
public void startup() {
someObject=new SomeObject(...arguments from environment which are not available until startup is called...);
}
public void shutdown() {
someObject=null; // this is not necessary, I am just expressing the intended scope of someObject explicitly
}
}
I can't make someObject final since it can't be set until startup() is invoked. But I would really like it to reflect its write-once semantics and be able to directly access it from multiple threads, preferably avoiding synchronization.
The idea being to express and enforce a degree of finalness, I conjecture that I could create a generic container, like so (UPDATE - corrected threading sematics of this class):
public class WormRef<T>
{
private volatile T reference; // wrapped reference
public WormRef() {
reference=null;
}
public WormRef<T> init(T val) {
if(reference!=null) { throw new IllegalStateException("The WormRef container is already initialized"); }
reference=val;
return this;
}
public T get() {
if(reference==null) { throw new IllegalStateException("The WormRef container is not initialized"); }
return reference;
}
}
and then in MyClass, above, do:
private final WormRef<SomeObject> someObject;
MyClass() {
someObject=new WormRef<SomeObject>();
}
public void startup() {
someObject.init(new SomeObject(...));
}
public void sometimeLater() {
someObject.get().doSomething();
}
Which raises some questions for me:
Is there a better way, or existing Java object (would have to be available in Java 4)?
Secondarily, in terms of thread safety:
Is this thread-safe provided that no other thread accesses someObject.get() until after its set() has been called. The other threads will only invoke methods on MyClass between startup() and shutdown() - the framework guarantees this.
Given the completely unsynchronized WormReference container, it is ever possible under either JMM to see a value of object which is neither null nor a reference to a SomeObject? In other words, does the JMM always guarantee that no thread can observe the memory of an object to be whatever values happened to be on the heap when the object was allocated. I believe the answer is "Yes" because allocation explicitly zeroes the allocated memory - but can CPU caching result in something else being observed at a given memory location?
Is it sufficient to make WormRef.reference volatile to ensure proper multithreaded semantics?
Note the primary thrust of this question is how to express and enforce the finalness of someObject without being able to actually mark it final; secondary is what is necessary for thread-safety. That is, don't get too hung up on the thread-safety aspect of this.
I would start by declaring your someObject volatile.
private volatile SomeObject someObject;
Volatile keyword creates a memory barrier, which means separate threads will always see updated memory when referencing someObject.
In your current implementation some threads may still see someObject as null even after startup has been called.
Actually this volatile technique is used a lot by collections declared in java.util.concurrent package.
And as some other posters suggest here, if all else fails fall back to full synchronization.
I would remove the setter method in WoRmObject, and provide a synchronised init() method which throws an exception if (object != null)
Consider using AtomicReference as a delegate in this object-container you're trying to create. For example:
public class Foo<Bar> {
private final AtomicReference<Bar> myBar = new AtomicReference<Bar>();
public Bar get() {
if (myBar.get()==null) myBar.compareAndSet(null,init());
return myBar.get();
}
Bar init() { /* ... */ }
//...
}
EDITED: That will set once, with some lazy-initialization method. It's not perfect for blocking multiple calls to a (presumably expensive) init(), but it could be worse. You could stick the instantiation of myBar into constructor, and then later add a constructor that allows assignment as well, if provided the correct info.
There's some general discussion of thread-safe, singleton instantiation (which is pretty similar to your problem) at, for example, this site.
In theory it would be sufficient to rewrite startup() as follows:
public synchronized void startup() {
if (someObject == null) someObject = new SomeObject();
}
By the way, although the WoRmObject is final, threads can still invoke set() multiple times. You'll really need to add some synchronization.
update: I played a bit round it and created an SSCCE, you may find it useful to play a bit around with it :)
package com.stackoverflow.q2428725;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String... args) throws Exception {
Bean bean = new Bean();
ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
executor.schedule(new StartupTask(bean), 2, TimeUnit.SECONDS);
executor.schedule(new StartupTask(bean), 2, TimeUnit.SECONDS);
Future<String> result1 = executor.submit(new GetTask(bean));
Future<String> result2 = executor.submit(new GetTask(bean));
System.out.println("Result1: " + result1.get());
System.out.println("Result2: " + result2.get());
executor.shutdown();
}
}
class Bean {
private String property;
private CountDownLatch latch = new CountDownLatch(1);
public synchronized void startup() {
if (property == null) {
System.out.println("Setting property.");
property = "foo";
latch.countDown();
} else {
System.out.println("Property already set!");
}
}
public String get() {
try {
latch.await();
} catch (InterruptedException e) {
// handle.
}
return property;
}
}
class StartupTask implements Runnable {
private Bean bean;
public StartupTask(Bean bean) {
this.bean = bean;
}
public void run() {
System.out.println("Starting up bean...");
bean.startup();
System.out.println("Bean started!");
}
}
class GetTask implements Callable<String> {
private Bean bean;
public GetTask(Bean bean) {
this.bean = bean;
}
public String call() {
System.out.println("Getting bean property...");
String property = bean.get();
System.out.println("Bean property got!");
return property;
}
}
The CountDownLatch will cause all await() calls to block until the countdown reaches zero.
It is most likely thread safe, from your description of the framework. There must have been a memory barrier somewhere between calling myobj.startup() and making myobj available to other threads. That guarantees that the writes in startup() will be visible to other threads. Therefore you don't have to worry about thread safety because the framework does it. There is no free lunch though; everytime another thread obtains access to myobj through the framework, it must involve sync or volatile read.
If you look into the framework and list the code in the path, you'll see sync/volatile in proper places that make your code thread safe. That is, if the framework is correctly implemented.
Let's examine a typical swing example, where a worker threads does some calculation, saves the results in a global variable x, then sends a repaint event. The GUI thread upon receiving the repaint event, reads the results from the global variable x, and repaints accordingly.
Neither the worker thread nor the repaint code does any synchronization or volatile read/write on anything. There must be tens of thousands of implementations like this. Luckily they are all thread safe even though the programmers paid no special attention. Why? Because the event queue is synchronized; we have a nice happends-before chain:
write x - insert event - read event - read x
Therefore write x and read x are properly synchronized, implicitly via event framework.
how about synchronization?
No it is not thread safe. Without synchronization, the new state of your variable might never get communicated to other threads.
Yes, as far as I know references are atomic so you will see either null or the reference. Note that the state of the referenced object is a completely different story
Could you use a ThreadLocal that only allows each thread's value to be set once?
There are a LOT of wrong ways to do lazy instantiation, especially in Java.
In short, the naive approach is to create a private object, a public synchronized init method, and a public unsynchronized get method that performs a null check on your object and calls init if necessary. The intricacies of the problem come in performing the null check in a thread safe way.
This article should be of use: http://en.wikipedia.org/wiki/Double-checked_locking
This specific topic, in Java, is discussed in depth in Doug Lea's 'Concurrent Programming in Java' which is somewhat out of date, and in 'Java Concurrency in Practice' coauthored by Lea and others. In particular, CPJ was published before the release of Java 5, which significantly improved Java's concurrency controls.
I can post more specifics when I get home and have access to said books.
This is my final answer, Regis1 :
/**
* Provides a simple write-one, read-many wrapper for an object reference for those situations
* where you have an instance variable which you would like to declare as final but can't because
* the instance initialization extends beyond construction.
* <p>
* An example would be <code>java.awt.Applet</code> with its constructor, <code>init()</code> and
* <code>start()</code> methods.
* <p>
* Threading Design : [ ] Single Threaded [x] Threadsafe [ ] Immutable [ ] Isolated
*
* #since Build 2010.0311.1923
*/
public class WormRef<T>
extends Object
{
private volatile T reference; // wrapped reference
public WormRef() {
super();
reference=null;
}
public WormRef<T> init(T val) {
// Use synchronization to prevent a race-condition whereby the following interation could happen between three threads
//
// Thread 1 Thread 2 Thread 3
// --------------- --------------- ---------------
// init-read null
// init-read null
// init-write A
// get A
// init-write B
// get B
//
// whereby Thread 3 sees A on the first get and B on subsequent gets.
synchronized(this) {
if(reference!=null) { throw new IllegalStateException("The WormRef container is already initialized"); }
reference=val;
}
return this;
}
public T get() {
if(reference==null) { throw new IllegalStateException("The WormRef container is not initialized"); }
return reference;
}
} // END PUBLIC CLASS
(1) Confer the game show "So you want to be a millionaire", hosted by Regis Philburn.
Just my little version based on AtomicReference. It's probably not the best, but I believe it to be clean and easy to use:
public static class ImmutableReference<V> {
private AtomicReference<V> ref = new AtomicReference<V>(null);
public boolean trySet(V v)
{
if(v == null)
throw new IllegalArgumentException("ImmutableReference cannot hold null values");
return ref.compareAndSet(null, v);
}
public void set(V v)
{
if(!trySet(v)) throw new IllegalStateException("Trying to modify an immutable reference");
}
public V get()
{
V v = ref.get();
if(v == null)
throw new IllegalStateException("Not initialized immutable reference.");
return v;
}
public V tryGet()
{
return ref.get();
}
}
First question: Why can't you just make start up a private method, called in the constructor, then it can be final. This would ensure thread safety after the constructor is called, as it is invisible before and only read after the constructor returns. Or re-factor your class structure so that the start-up method can create the MyClass object as part of its constructor. In may ways this particular case seems like a case of poor structure, where you really just want to make it final and immutable.
The easy Approach, if the class is immutable, and is read only after it is created, then wrap it in an Immutable List from guava. You can also make your own immutable wrapper which defensively copies when asked to return the reference, so this prevents a client from changing the reference. If it is immutable internally, then no further synchronization is needed, and unsynchronized reads are permissible. You can set your wrapper to defensively copy on request, so even attempts to write to it fail cleanly (they just don't do anything). You may need a memory barrier, or you may be able to do lazy initialisation, although note that lazy initialisation may require further synchronization, as you may get several unsynchronized read requests while the object is being constructed.
The slightly more involved approach would involve using an enumeration. Since enumerations are guaranteed singleton, then as soon as the enumeration is created it is fixed for ever. You still have to make sure that the object is internally immutable, but it does guarantee its singleton status. Without much effort.
The following class could answer your question. Some thread-safety achieved by using a volatile intermediate variable in conjunction with final value keeper in the provided generic. You may consider further increase of it by using synchronized setter/getter. Hope it helps.
https://stackoverflow.com/a/38290652/6519864

Categories

Resources