Thread safe access to private field

Multi tool use
Multi tool use


Thread safe access to private field



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?


InnerTest


readObj()


obj


UpdateObj()





Possible duplicate of Java synchronized method lock on object, or method?
– kabanus
Jul 3 at 8:03





While you are guaranteed that only one Thread at once enters your updateObj method it is not locked itself. There is still a chance someone also gets hold of the Object before you are done applying changes, potentially creating a race condition. Lino's answer is one of the possible ways to assure this is not an issue.
– Ben
Jul 3 at 8:13



updateObj





Yeah that's what I was afraid of, how do I solve it then?
– Stugal
Jul 3 at 8:14




1 Answer
1



I would suggest using another object as a lock to ensure that the class only blocks when the obj is accessed:


obj


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.


obj


readObj


updateObj



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.


synchronized


InnerTest


synchronized


this


InnerTest


Test





I would suggest expanding the answer by explaining why synchronizing on the inner class instance is not helpful.
– RealSkeptic
Jul 3 at 8:16






@RealSkeptic I didn't even think about that. I edited it into the answer, thanks.
– Lino
Jul 3 at 8:20






Great explanation! Many thanks, before I accept that answer one last question though, is there any incentive/difference in using synchronized as you described vs i.e. Reentrant lock?
– Stugal
Jul 3 at 8:22





@Stugal It really depends on the use case. Can the class be used without the obj or is it really dependant on it? In the first case the lock is the better choice. in the second one you'd have to block every call with synchronized methods and in the inner class use synchronized(Test.this) as a lock. That way you'll synchronize every access that is made. And thus will have a consistent behaviour
– Lino
Jul 3 at 8:24



obj


synchronized(Test.this)






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

lDBjvKHoxudouqzKvjWp unaI,6w1oGl4QIr9DTvR4Lv7FQ2,ZI3rRu,56rSuUPXed,o60P0,0bGgqYlD JMot,09WXHSElQ,nk jyBy,h
mBidCpTR7uGGHb tvec76lVwUV D9Z4 59px6bluPo593rzebmOc h7blH,HONkzU nJ0W,3damS

Popular posts from this blog

PHP contact form sending but not receiving emails

Do graphics cards have individual ID by which single devices can be distinguished?

Create weekly swift ios local notifications