Win a copy of TensorFlow 2.0 in Action this week in the Artificial Intelligence and Machine Learning forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Paul Clapham
  • Bear Bibeault
  • Jeanne Boyarsky
Sheriffs:
  • Ron McLeod
  • Tim Cooke
  • Devaka Cooray
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Jj Roberts
  • Stephan van Hulst
  • Carey Brown
Bartenders:
  • salvin francis
  • Scott Selikoff
  • fred rosenberger

A(nother) thread question

 
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just read something and I'm not convinced.

I read that is a valid lock.

Two questions :
1). Doesn't the reference have to be final ( to ensure that another thread acquiring this lock doesn't read null)
2). Does it matter about the thread safety of the type you're using ? I've read that any type will do.

Thanks
 
Marshal
Posts: 70709
288
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Any object can be locked. Then you can write synchronized (myObject) ...
You will of course suffer an exception if myObject points to null. Maybe it is a good idea to make that reference final, but making it private without any means of reassigning it should suffice. Make sure it is definitely assigned to before any of those methods is called, so calling one of those methods with synchronisation from the constructor would be a bad idea.
The Object class has some bits set aside for locking and a particular Thread takes ownership of the lock, so it can be used for synchronisation and that applies to every subtype of Object (i.e. everything). Most people would use an instance of the Lock interface nowadays.
 
Saloon Keeper
Posts: 242
39
Firefox Browser MySQL Database Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Where did you read that? Without the context I'm not sure what you mean by valid lock.

You can use any object in synchronised statement. This is valid:

It would be interesting if 'lock' were reassigned in the mean time, though.

[Edit] I'm far too slow
 
Michael Farragher
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But even if you made the reference private, if one thread set the reference and another thread used it in a synchronized method, it might still evaluate to null ?!?
 
Campbell Ritchie
Marshal
Posts: 70709
288
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Check the order of instantiation of class members. I think you will find that static field is instantiated immediately after the class is loaded and before any methods can be called. Have a look in the Java® Language Specification. Try this section, and the Virtual Machine Specification.
 
Marshal
Posts: 25965
70
Eclipse IDE Firefox Browser MySQL Database
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Michael Farragher wrote:2). Does it matter about the thread safety of the type you're using ? I've read that any type will do.



The object only exists to support locking and synchronization (at least, that's all you should be using it for). So you aren't going to be calling any of its methods. And yeah, any type will do but if you don't use Object then future readers of your code are going to have to stop and ask why you used some other type. You shouldn't make them do that.
 
Saloon Keeper
Posts: 12436
269
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The relevant part is "Initialization" in the JVMS: https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-5.html#jvms-5.5

Virtual Machines are required to synchronize on the class object during initialization. That means that static fields that have an initializer will never be observed to still have their default value when accessed from another thread concurrently during initialization. It's still good practice to make them final though, for the simple fact that static fields should be used for nothing but constants.

The matter is a bit different for instance fields. There is no implicit synchronization when creating a new instance of a class, so non-final fields can be observed to have their default value, even if you initialize them immediately when declaring them. Using the final keyword is very important here, because it ensures that other threads will always see the initialized value and never the default value.
 
Campbell Ritchie
Marshal
Posts: 70709
288
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can you prevent that latter problem by synchronising the constructor, Stephan? I know you can sometimes cause that particular problem by allowing a this reference to escape the constructor.
 
Michael Farragher
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for that, Stephen.

Based on your last sentence above, the following isn't good enough :



lock must be final. Otherwise, another thread could read it as null

(I spend a lot of my time thinking about threads ;))
 
Stephan van Hulst
Saloon Keeper
Posts: 12436
269
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Can you prevent that latter problem by synchronising the constructor, Stephan?


You can't synchronize the constructor itself, but you can use the synchronized keyword inside a constructor. This would indeed prevent other threads from seeing uninitialized fields, but it is not recommended. If you really want to immediately share a newly created mutable object with another thread, it's better to introduce a happens-before relationship in the calling method between the object creation and the sharing of the object reference. An easy way to do this is by assigning the newly created object to a volatile field.

I know you can sometimes cause that particular problem by allowing a this reference to escape the constructor.


You don't need a contrived scenario for this to happen. This is enough:

Most of the time, this code will either print "Initialized!" or it will throw a NullPointerException because shared has not been assigned an object reference yet. Rarely however, this code might also print "null" because the object reference has been assigned to shared before "Initialized!" has been assigned to shared.nonFinalField.

You might ask how it's possible that shared is assigned a reference to an object that hasn't finished constructing yet, but without explicit synchronization the thread that creates the ObjectWithNonFinalField is allowed to do exactly this, under Java 1.5's memory model.
 
Stephan van Hulst
Saloon Keeper
Posts: 12436
269
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Michael Farragher wrote:lock must be final. Otherwise, another thread could read it as null


This is a very interesting example. I don't know for sure.

If thread1 creates the instance of LockTest and shares the instance without synchronization, then thread2 might call setANumber() on the shared instance before the lock field was initialized. What happens next depends on how the synchronized keyword functions exactly. Will it first update the lock field before it reads it, thereby synchronizing on the proper lock object, or will it throw a NullPointerException? I bet it will throw an exception, because synchronizing on the variable before synchronizing on the value it holds makes no sense and would add way too much overhead.

So no, I don't think the code you wrote is good enough. However, as I pointed out before, even IF it was good enough you'd still want to make your lock field final, because it's a super bad idea to change the lock during the lifetime of the object.
 
Michael Farragher
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Another interesting question is : what part of type Object is used as the 'lock' ?

Is the lock dependent on fields ? If so, are these fields thread safe
 
Jj Roberts
Saloon Keeper
Posts: 242
39
Firefox Browser MySQL Database Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Every object has an intrinsic lock, also called a monitor built into it. This is what is used to manage synchronization.
From Oracle's Java Tutorials

Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.

Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.

 
Stephan van Hulst
Saloon Keeper
Posts: 12436
269
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It is as JJ said, objects have an intrinsic lock. You can think of it as some kind of hidden field that only the JVM itself has access to.

It's a bit of pity that they took this approach. It would have been better to encapsulate the intrinsic lock in a dedicated type, similar to java.util.concurrent.locks.Lock and then maybe only allow the synchronized keyword to be used on Lock references, similar to how try-with-resources uses AutoCloseable references.
 
Remember to always leap before you look. But always take the time to smell the tiny ads:
Thread Boost feature
https://coderanch.com/t/674455/Thread-Boost-feature
reply
    Bookmark Topic Watch Topic
  • New Topic