Would locking via ReadWriteLock or synchronize(this) block a rendering thread?
Im writing an adapter between loader where I can't change the code, for example;
class LoaderAdapter implements Loader {
private AnotherLoader.Callback callback = new AnotherLoader.Callback() {
// Called on render thread
public void onLoaded(Data data) {
if (mData.equals(data)) {
return;
}
mData = data;
notifyListeners();
}
};
private final AnotherLoader loader = ...
private Data mData;
// Called on render thread
@Override
public start() {
loader.start();
}
// Called on background thread
@Override
public List<Items> getContent() {
//iterate over contents
return processor.process(mData);
}
}
I don't think this is thread safe as mData is written to on the render thread, but reads are from a background thread.
In an attempt to fix this I added a ReadWriteLock;
class LoaderAdapter implements Loader {
private AnotherLoader.Callback callback = new AnotherLoader.Callback() {
// Called on render thread
public void onLoaded(Data data) {
lock.writeLock().lock();
try {
mData = data;
} finally {
lock.writelock().unlock();
}
}
};
private final AnotherLoader loader = ...
private final ReentrantReadWriteLock lock ....
private Data mData;
// Called on render thread
@Override
public start() {
loader.start();
}
// Called on background thread
@Override
public List<Items> getContent() {
lock.readLock().lock();
try {
return processor.process(mData);
} finally {
lock.readLock().unlock();
}
}
}
Now the problem is onLoaded() is called on the render thread and I would be calling .lock(). Would this block the render thread and potentially slow rendering?
Is there a way to handle this, whilst working between the two classes I can't change? One option I thought of was to run the contents of onLoaded() on a BG thread to avoid locking on the render thread. However I wonder if there is a more elegant way of doing this.
Yes, this would block the render thread since the write lock can be acquired only if no read locks are held.
Using a lock is overkill in this case. The solution is to declare mData
volatile:
private volatile Data mData;