Thread safe access to private field - java

So I have the following scenario (can't share the actual code, but it would be something like this):
public class Test
{
private Object obj;
public void init()
{
service.registerListener(new InnerTest());
}
public void readObj()
{
// read obj here
}
private class InnerTest implements Listener
{
public synchronized void updateObj()
{
Test.this.obj = new Object();
// change the obj
}
}
}
The InnerTest class is registered as listener in a service. That Service is running in one thread the calls to readObj() are made from a different thread, hence my question, to ensure consistency of the obj is it enough to make the UpdateObj() method synchronized?

I would suggest using another object as a lock to ensure that the class only blocks when the obj is accessed:
public class Test
{
private final Object lock = new Object();
private Object obj;
public void init()
{
service.registerListener(new InnerTest());
}
public void readObj()
{
synchronized(lock){
// read obj here
}
}
private class InnerTest implements Listener
{
public void updateObj()
{
synchronized(Test.this.lock){
Test.this.obj = new Object();
// change the obj
}
}
}
}
Then use that lock in all methods that need to have consistent access to obj. In your current example the readObj and updateObj methods.
Also as stated in the comments, using synchronized on the method level in your InnerTest class, will not really work as you probably intended. That is, because synchronized methods will use a synchronized block on the this variable. Which just blocks your InnerTest class. But not the outer Test class.

Related

Visibility of mutable object under different locks in Java

mFeaute is a mutable object.
I want to know if the change of mFeature in setFeature(Feature feature) is visible to mFeature in useFeature(...) with a different explicit form of synchronized.
Thanks.
public class FeatureService {
private static Feature mFeature= null;
private final Object MUTEX = new Object();
...
static void setFeature(Feature feature){
// doSomething
synchronized (FeatureService.class){
mFeature = feature;
// doSomething
}
// doSomething
}
public void useFeature(...){
// doSomething
synchronized (MUTEX){
someFunction(mFeature);
// doSomething
}
// doSomething
}
}
}
The above code is suffering from a data race and hence is broken. You do not have a happens before edge between the write and the read of mfeature because different locks are used. You need to use the same lock instance for both reading and writing.
It is unclear what you are trying to synchronize on (ClassA and ObjectB are vague). In general, you want to synchronize on a single mutex when interacting with a given shared resource. Create an Object to serve as the mutex upon which you synchronize when accessing the internal mFeature.
public class FeatureService {
private static Feature mFeature= null;
private static final Object MUTEX = new Object();
...
static void setFeature(Feature feature){
synchronized (MUTEX){
mFeature = feature;
}
}
public void useFeature(...){
synchronized (MUTEX){
someFunction(mFeature);
}
}
}

Reset mutable class fields

Say I have a class with some mutable fields:
public class Test
{
private boolean isCorrect;
private String userId;
public void run() {...}
// more methods
}
The run() method will be modifying these fields. My issues is that the caller of this class might call run() any number of times, and for this reason I should be re-setting the fields back to null.
My question is, what is the best practice for this scenario? Should I reset the fields every time the method is called?
public void run()
{
isCorrect = null;
userId = null;
// do stuff
}
Or is there a cleaner/smarter approach to this?
The simple answer is use local variables. The OP has clarified in the comments that run calls other methods on the same instance that expect to use these variable too.
The class should be split. The run method should create an object containing the fields and call methods on that.
public class Test {
public void run() {
TestImpl impl = new TestImpl();
impl.run();
}
// more methods
}
class TestImpl {
private boolean isCorrect;
private String userId;
public void run() {...}
// more methods
}
You could make the new class a nested class, though that does cause excessive indention. An inner class would also have direct access to any longer lived variables of Test. An anonymous inner class (or, more obscurely, a local class) would be even more convenient but indented.
I would do it this way. Using an exception. So anyone who dares to use run() twice gets kicked out.
package test;
import com.sun.jdi.IncompatibleThreadStateException;
public class Test{
private boolean isRunning = false;
public void run() throws IncompatibleThreadStateException{
if(this.isRunning) {
throw new IncompatibleThreadStateException();
}
else {
this.isRunning = true;
}
}
public static void main(String[] args) {
}
}

How to resolve this deadlock?

I have added comments in code to explain from where deadlock is occurring.
Basically, There are two threads. Each thread acquires lock on an Manager object and then go for acquiring lock on static resource, which is a map of all the Manager objects in the application.Both thread calls get() on map.
Manager class has overridden equals() method. equals() further calls some synchronized method of Manager class. So a get() on map will need object level lock on each object in the map one by one until key matches because equals is overridden.
I can only change the code in sub classes(Sub1 and Sub2) and avoid the deadlock, as I don't have access to other classes.
Edit: I don't have access to syncMap. The code in 'synchronized' block executes in third party code whose API I call to.
Can I avoid this by acquiring lock in finally on Manager, rather than before try block ?!
public class Parent{
protected Manager manager;
}
public class Global{
private static final Map syncMap = Collections.synchronizedMap(new HashMap());
//syncMap contains all the objects of Manager in the application
}
class Manager{
public boolean equals(Object o){
Manager obj = (Manager)o;
return obj.getURL().equals(getURL());
}
public final synchronized String getURL(){
return msettings.getDBURL(); //msettings is a global variable
}
}
//Thread-1 is executing someMethod() of this class
class Sub1 extends Parent{
Global global;
//consider manager and Global object are not null
public void someMethod()
{
synchronized(manager){// Thread-1 succesfully takes object level lock on a manager object, say Manager01
try{
global.syncMap.get(manager);
// Thread-1 Succesfully takes class level lock on syncMap
// get() calls equals() for each object in syncMap.
//equals() need object lock on each Manager Object in map as it further calls synchronized getURL()
// But on one manager Object(Manager02) Thread-2 has already acquired lock and is waiting for lock on syncMap which this thread-1 holds
}
finally{
manager.releaseConnection();
}
}
}
}
//Thread-2 is executing otherMethod() of this class
class Sub2 extends Parent{
public void otherMethod()
{
synchronized(manager){// this takes a lock on manager(Manager02)
try{
global.syncMap.get(manager);
// this is blocked as syncMap is aquired by thread-1
}
finally{
manager.releaseConnection();
}
}
}
}
After new portion of information I don't see another solution except of turning all processing into serial-style. So you can put all manager-associated API calls in one synchronized method of some wrapping class and use this wrapper as a single entry-point for third-party API.
class BrutalWrapper {
public synchronized void doIt(Manager manager)
{
try{
global.syncMap.get(manager);
}
finally{
manager.releaseConnection();
}
}
}
class Sub1 extends Parent{
BrutalWrapper brutal;
public void someMethod()
{
brutal.doIt(manager);
}
}
class Sub2 extends Parent{
BrutalWrapper brutal;
public void someMethod()
{
brutal.doIt(manager);
}
}
First of all, you really should try to eliminate the need for synchronization in the equals method. It will cause more trouble than it solves so if a redesign is possible then I think thats the best way.
However, if you restructure the code a bit and move the global.syncMap.get(manager) to before the synchronization block it would not generate a deadlock
public Class Parent{
protected Manager manager;
}
class Global{
private static final Map syncMap = Collections.synchronizedMap(new HashMap());
//syncMap contains all the objects of Manager in the application
}
class Manager{
public boolean equals(Object o){
Manager obj = (Manager)o;
return obj.getURL().equals(getURL());
}
public final synchronized String getURL(){
return msettings.getDBURL(); //msettings is a global variable
}
}
//Thread-1 is executing someMethod() of this class
class Sub1 extends Parent{
Global global;
//consider manager and Global object are not null
public void someMethod()
{
try {
global.syncMap.get(manager);
synchronized(manager){
}
}
finally{
manager.releaseConnection();
}
}
}
//Thread-2 is executing otherMethod() of this class
class Sub2 extends Parent{
public void otherMethod()
{
try {
global.syncMap.get(manager);
synchronized(manager){
}
}
finally{
manager.releaseConnection();
}
}
}
UPDATE Alternative synchronization over Global.class, could probably use instance variable global also instead of Global.class
UPDATE Changed synchronization to be over Manager.class instead of Global.class.
class Sub1 extends Parent
{
Global global;
public void someMethod()
{
synchronized (Manager.class) {
try {
global.syncMap.get(manager);
}
finally {
manager.releaseConnection();
}
}
}
}
class Sub2 extends Parent
{
Global global;
public void otherMethod()
{
synchronized (Manager.class) {
try {
global.syncMap.get(manager);
}
finally {
manager.releaseConnection();
}
}
}
}

Synchronizing two methods in Java

I have a class like this one:
public class IClass{
public void draw(){...}; //is called periodically by the rendering thread
public void foo(){...}; //is called asynchronously from another Thread(it could be an onTouchEvent() method for example)
}
I want the foo() method to wait until the draw method is finished and vice versa. How can I do this in Java?
regards
Make the methods synchronized.
public synchronized void draw() { System.out.println("draw"); }
public synchronized void foo() { System.out.println("foo"); }
Or synchronize on the same object.
private static final Object syncObj = new Object();
public void draw() {
synchronized (syncObj) {
System.out.println("draw");
}
}
public void foo() {
synchronized (syncObj) {
System.out.println("foo");
}
}
Putting synchronized on a method means the thread has to acquire the lock on the object instance before entering that method, so if you have two different methods marked synchronized the threads entering them will be contending for the same lock, and once one thread gets the lock all other threads are shut out of all methods that synchronize on that same lock. So in order for the two methods to run concurrently they would have to use different locks, like this:
public class IClass {
private final Object lockDraw = new Object();
private final Object lockFoo = new Object();
public void draw() {
synchronized(lockDraw) {
//method draw
}
}
public void foo() {
synchronized(lockFoo) {
//method foo
}
}
}
Both methods lock the same monitor. Therefore, you can't simultaneously execute them on the same object from different threads (one of the two methods will block until the other is finished).

Clear Singleton instance in Java

I have a Singleton class to save the state of an application's module.
This class simply have a lot of class variables with setters and getters :
public class ModuleState{
private static ModuleState instance;
private A a;
private B b;
private C c;
..
..
..
..
private ModuleState (){}
public ModuleState getInstance(){
if(instance==null)
instance=new ModuleState();
return instance;
}
}
At a precise moment of the application lifecycle, i have the need to CLEAR the module's state. What i do now is to reset ALL the variables in ModuleState by a clearAll() method like this:
public void clearAll(){
a=null;
b=null;
c=null;
..
..
}
My question is the following : there is a cleaner method to do this reset? Possibly clearing the singleton instance itself, without resetting every class variable?
The problem with this approach is that i may have the need to add a new class variable to the ModuleState. In this case i must remember to add a line in the clearAll() method to reset the new variable.
What about ...
public static volatile ModuleState instance = null;
public static void reset() {
instance = new ModuleState();
}
p.s.: as per discussion below: in a multithreaded environment it's very important to synchronize the access on the instance because the JVM is allowed to cache its value. You can use volatile as shown above. Thanks to all!
Cheers!
no, this approach is perfectly acceptable. you are of course synchronizing access to these state objects in some way, right? otherwise you risk someone seeing a half-cleared config object.
another thing you could do to future-proof yourself against any extra state added in the future is store all of your state in a HashMap, for example, instead of individual fields. this way, clear()ing the hashmap ensures that all state is wiped and adding any extra state in the future becomes safer
You need to maintain the same object instance, in order to comply with the Singleton pattern, so your approach makes sense: altering the members.
However, if you wanted to clean it up a little bit, why not just have an internal list, like:
ArrayList<Object> members = new ArrayList<Object>();
// If it actually is Object, there's no need to paramaterize.
// If you want, you can actually make the members implement a common interface,
// and parameterize the ArrayList to that.
Another Option would be to have a HashMap, that binds the key word to the member.
HashMap<String,Object> members = new HashMap<String,Object>();
// Again, same parameterization rules apply.
For an ArrayList or a HashMap, the clearAll method might look like this:
public class ModuleState()
{
public void clearAll()
{
members.clear();
}
}
This method won't need to change.
May be this can help you:
public class SingletonBean {
private static SingletonBean instance = new SingletonBean();
private static Object privateMutex = new Object();
private SingletonBean() {
//to prevent instantiation
}
public class ObjectsContainer {
private Object A;
private Object B;
private Object C;
public Object getA() {
return A;
}
public void setA(Object a) {
A = a;
}
public Object getB() {
return B;
}
public void setB(Object b) {
B = b;
}
public Object getC() {
return C;
}
public void setC(Object c) {
C = c;
}
}
private ObjectsContainer objectsContainer;
private void resetObjectsContainer() {
objectsContainer = new ObjectsContainer();
}
public static SingletonBean getInstance() {
return SingletonBean.instance;
}
public static void clearAll() {
synchronized (privateMutex) {
SingletonBean.getInstance().resetObjectsContainer();
}
}
public static ObjectsContainer getObjectsContainer() {
synchronized (privateMutex) {
return instance.objectsContainer;
}
}
}
public class SomeClass {
public void someMethod() {
SingletonBean.getObjectsContainer().getA();
}
}
Make an inner class to hold the fields, then replace that instance when you want to reset. The write to the field would make the change to all three fields essentially atomic.
public class ModuleState {
private static volatile ModuleState instance;
private static class Values {
A a;
B b;
C c;
}
private volatile Values values = new Values()(
private ModuleState (){}
public ModuleState getInstance(){
if (instance==null) {
synchronized (ModuleState.class) {
if (instance==null) {
instance = new ModuleState();
}
}
}
return instance;
}
public synchronized A getA() {
return values.a;
}
public synchronized void reset() {
values = new Values();
}
By the way, your null checking initialization code was not threadsafe. I fixed that too.
Note that to make this work, you must make the reference to values volatile and synchronize all access to it, otherwise (due to the java memory model) other threads than the one that calls reset() may see the old reference.

Categories