In another thread I came across this question, so I have to put it here as a simple and focused question.
void method(){
Machine machine = new Machine();
...
}
class Machine{
private static Tool tool = new Tool();
...
}
Although Machine is a local variable in method(), it's still thread unsafe because Machine has a static instance variable 'tool' that could be potentially thread unsafe, since all threads will share this 'tool' object due to static.
So if Machine is thread safe by itself through whatever way, then it can be safely stated that "the local variable machine" is thread safe. Otherwise, it's not safe, even though 'machine' is a local variable.
Is this understanding correct?
Yes, this understanding is correct. Only the variable itself is thread-safe, in the sense that other threads will not modify its value concurrently.
This protection does not extend to the object referenced by your local variable: depending on the object's inner construction, such as mutability and use of static variables, the object may or may not be thread-safe.
Note that local variables of primitive types and local variables referencing immutable objects are always thread-safe.
Yes, the statement local variables are thread safe comes with a couple of conditions.
Firstly, let's look at why local variables are thread safe. This is because the variables are allocated on the method's own stack frame, which is NOT shared with any other execution path.
So, it is important to note that the variable itself is thread-safe, NOT necessarily what it points to. In other words:
Primitive variables are completely thread safe, because the value is on the stack itself
Object references is a more complicated story, because the actual object is created on the heap and the stack frame just points to the heap memory.
In the image below, the integer variable is thread safe but the Object and Array are not.
Whether the object is thread-safe entirely depends on whether the class is designed to be thread-safe or not.
So if Machine is thread safe by itself through whatever way, then it can be safely stated that "the local variable machine" is thread safe.
It can always and unconditionally be stated that the 'local variable machine' is thread-safe', regardless of the thread-safety of any object it refers to.
Otherwise, it's not safe, even though 'machine' is a local variable.
If 'it' refers to the local variable, it is always thread-safe.
Is this understanding correct?
No. You are confusing variables with objects.
Local variables, such as machine in your example, are thread-safe, period.
Objects are or are not thread-safe depending on what's inside them, regardess of where and how they are referenced, i.e. in this case whether or not the object that is an instance of Machine is referenced by the local variable machine.
Related
While reading the documentation related to Threads and Locks, a sentence describing final keyword attracted me:
Correspondingly, compilers are allowed to keep the value of a final field cached in a register and not reload it from memory in situations where a non-final field would have to be reloaded.
Does it mean, that if I declare a final Object object = ... as an instance variable and then access it (modify its inner state - object.state) from anonymous inner classes (multiple instances of Runnable), then the value of object.state could actually be read/written from/into CPU cache and it (value of object.state) could be out of sync across those Runnable instances?
So if I want to be sure, that the value of object.state is properly propagated across all the threads I have to declare the object as volatile Object object instead?
Thank you.
Edit: I have edited my original question. And now I know I misunderstood the documentation so the answer to my last question is NO - volatile/final Object object has no effect on object.state - it depends how the object.state is declared, initialized and/or accessed.
Thanks to the #Burak Serdar for the answer!
When you declare a final Object object=..., the final value is the reference to the object, not the internal state of the object. It means than nothing can modify object, it does not say that nothing can modify, say, object.value. So the variable object can be cached, which does not mean the internal state of object can be cached.
Final will not help you with threading issues the way you hope, sorry.
Volatile may help in some situations, but you may need a lock.
From the Oracle tutorials:
-Reads and writes are atomic for reference variables and for most primitive variables (all types except long and double).
-Reads and writes are atomic for all variables declared volatile (including long and double variables).
That means your object will not be immediately updated between reads and writes, but it will be consistent within one read/write.
when writing concurrency program, sometimes we use the reference parameter, assume it is ref1 with fake type Reference, a method like
public void testRefVarInMethod(Reference ref1) {
Reference ref2 = ref1;
....
....
}
In this method, I declare a new variable ref2 which points to ref1. We all know that method variable is thread safe, however, as to reference ref1, anybody can change its value outside the method, so the ref2's value will be changed too. I guess this cannot guarantee thread safe, why do some people write code like this?
That's why people use methods like clone to ensure thread-safety.
Reference ref2 = ref1.clone();
By referencing the copy of ref1, ref2 will not be affected regardless how ref1 is changed by some other threads.
Edit:
As pointed out in the comments, the clone method does not necessarily enforce thread-safety. It has to be correctly implemented in a way that modifying ref1 will not change the state of ref2. i.e., ref1 and ref2 do not share any mutable fields.
The value of the local variable ref2 itself cannot be changed outside your method (none can make it point to another object from outside). It's only the state of the object it references that can be changed (someone can call ref1.setField(newValue)) concurrently.
People do that because they need to share objects between threads. Otherwise, they wouldn't be able to gain benefits of multithreading in many cases.
But people don't do it recklessly, they usually introduce various forms of synchronization to guarantee thread safety. For instance, one can use synchronized section as the simplest and most straightforward tool to delineate a critical section that can be executed by only one thread at any given time:
synchronized(ref2) {
// Change or read object here
}
If all the code uses the same approach, making changes (and reading them) on the object will be safe.
There're many other, more specialised and more efficient, synchronization primitives and techniques that you should learn about if you're going to write multithreaded programs with shared objects: immutability, volatile, ReadWriteLock etc. Books like "Java Concurrency in Practice" can give you a good introduction into the field.
JMM (Java Memory Model) is free to reorder statements.
Of course, this is especially tricky when dealing with multithreading environment.
JMM rules precised that volatile and final variables are always fully initialized before constructor finishes and if and only if reference hasn't "escape" from within constructor.
It implies that "normal" variables (non-final and non-volatile) aren't expected to be seen up-to-date by any concurrent threads.
My question might seem stupid at first glance, but it really doesn't:
Are any object's references set AFTER constructor completes (completes not meaning with initialization of all variables already made, but simply reaching the end of the 'constructor' process)? Is there a rule in any JSR asserting it?
Or might it exist an exceptional case where any reference could be sent back to client BEFORE constructor completes?
Indeed, if statements reordering is reputed so free, it may also imply the sending of the object's reference 'happens-before' constructor completes. So, we'd come across the same case of the "this escape" to avoid.
To put it in a nutshell, is reference ALWAYS be sent after constructor completes?
After searching into the JLS: the only place where returning of object's reference is related is: (excerpt of JSR-12.5)
Just before a reference to the newly created object is returned as the
result, the indicated constructor is processed to initialize the new
object using the following procedure:
No relation to JMM ... therefore it can be ensured that constructor completion always happens-before passing reference whatever the case.
Within the context of a thread the reference will be set. However, the JMM allows shared variables to be set in one thread and not yet synchronised to the other thread.
Volatile and final guarantee this by guaranteeing inter-thread synchronisation of reads and writes to the variable.
I have a question about variable scope.
For example:
class A {
private static void test() {
// do something with local variables
}
}
Now I make two threads, and create one instance of A for each thread.
When I call test() in each thread, can I guarantee that test() is thread safe?
Where are the local varibles in test() stored? Each threads' stack? Heap space?
P.S. I know that static is totally pointless in this case. I found it in our legacy code; I just wanna make sure what I know!
Local variables are stored in each thread's own stack. That means that local variables are never shared between threads. That also means that all local primitive variables are thread safe.
Local references to objects are a bit different. The reference itself is not shared. The object referenced however, is not stored in each threads's local stack. All objects are stored in the shared heap. If an object created locally never escapes the method it was created in, it is thread safe. In fact you can also pass it on to other methods and objects as long as none of these methods or objects make the passed object available to other threads.
Object members are stored on the heap along with the object. Therefore, if two threads call a method on the same object instance and this method updates object members, the method is not thread safe.
Thread safety check: If a resource is created, used and disposed within the control of the same thread, and never escapes the control of this thread,the use of that resource is thread safe.
From: http://tutorials.jenkov.com/java-concurrency/thread-safety.html
When I call test() in each thread, can I guarantee that test() is thread safe?
Yes it would be thread safe if in test() method you are working on
method local variables.
Where are the local varibles in test() stored? each threads' stack? heap space?
Method Local variable are stored each thread's own stack.
For number 1, I don't know what test() does, so I cannot answer. If they modify some static variable of the class A, then it may not be thread safe. If both threads along the way are given reference to the same object, depending on how the object is defined, it might not be thread safe.
For number 2, local variables are in the stack of each thread (or at least conceptually like that), so there is no worry about the local variables being modified by the other threads.
I am reading Java Concurrency in Practice and kind of confused with the thread confinement concept. The book says that
When an object is confined to a thread, such usage is automatically thread-safe even if the confined object itself is not
So when an object is confined to a thread, no other thread can have access to it? Is that what it means to be confined to a thread? How does one keep an object confined to a thread?
Edit:
But what if I still want to share the object with another thread? Let's say that after thread A finishes with object O, thread B wants to access O. In this case, can O still be confined to B after A is done with it?
Using a local variable is one example for sure but that just means you don't share your object with other thread (AT ALL). In case of JDBC Connection pool, doesn't it pass one connection from one thread to another once a thread is done with that connection (totally clueless about this because I never used JDBC).
So when an object is confined to a thread, no other thread can have access to it?
No, it's the other way around: if you ensure that no other thread has access to an object, then that object is said to be confined to a single thread.
There's no language- or JVM-level mechanism that confines an object to a single thread. You simply have to ensure that no reference to the object escapes to a place that could be accessed by another thread. There are tools that help avoid leaking references, such as the ThreadLocal class, but nothing that ensures that no reference is leaked anywhere.
For example: if the only reference to an object is from a local variable, then the object is definitely confined to a single thread, as other threads can never access local variables.
Similarly, if the only reference to an object is from another object that has already been proven to be confined to a single thread, then that first object is confined to the same thread.
Ad Edit: In practice you can have an object that's only accessed by a single thread at a time during its lifetime, but for which that single thread changes (a JDBC Connection object from a connection pool is a good example).
Proving that such an object is only ever accessed by a single thread is much harder than proving it for an object that's confined to a single thread during its entire life, however.
And in my opinion those objects are never really "confined to a single thread" (which would imply a strong guarantee), but could be said to "be used by a single thread at a time only".
The most obvious example is use of thread local storage. See the example below:
class SomeClass {
// This map needs to be thread-safe
private static final Map<Thread,UnsafeStuff> map = new ConcurrentHashMap<>();
void calledByMultipleThreads(){
UnsafeStuff mystuff = map.get(Thread.currentThread());
if (mystuff == null){
map.put(Thread.currentThread(),new UnsafeStuff());
return;
}else{
mystuff.modifySomeStuff();
}
}
}
The UnsafeStuff objects itself "could be shared" with other threads in the sense that if you'd pass some other thread instead of Thread.currentThread() at runtime to the map's get method, you'd get objects belonging to other threads. But you are choosing not to. This is "usage that is confined to a thread". In other words, the runtime conditions are such that the objects is in effect never shared between different threads.
On the other hand, in the example below the object is automatically confined to a thread, and so to say, the "object itself" is confined to the thread. This is in the sense that it is impossible to obtain reference from other threads no matter what the runtime condition is:
class SomeClass {
void calledByMultipleThreads(){
UnsafeStuff mystuff = new UnsafeStuff();
mystuff.modifySomeStuff();
System.out.println(mystuff.toString());
}
}
Here, the UnsafeStuff is allocated within the method and goes out of scope when the method returns.. In other words, the Java spec is ensuring statically that the object is always confined to one thread. So, it is not the runtime condition or the way you use it that is ensuring the confinement, but more the Java spec.
In fact, modern JVM sometimes allocate such objects on stack, unlike the first example (haven't personally checked this, but I don't think at least current JVMs do).
Yet in other words, in the fist example the JVM can't be sure if the object is confined within a thread by just looking inside of calledByMultipleThreads() (who knows what other methods are messing with SomeClass.map). In the latter example, it can.
Edit: But what if I still want to
share the object with another thread?
Let's say that after thread A finishes
with object O, thread B wants to
access O. In this case, can O still be
confined to B after A is done with it?
I don't think it is called "confined" in this case. When you do this, you are just ensuring that an object is not accessed concurrently. This is how EJB concurrency works. You still have to "safely publish" the shared object in question to the threads.
So when an object is confined to a thread, no other thread can have access to it?
That's what thread confinement means - the object can only EVER be accessed by one thread.
Is that what it means to be confined to a thread?
See above.
How does one keep an object confined to a thread?
The general principle is to not put the reference somewhere that would allow another thread to see it. It is a little bit complicated to enumerate a set of rules that will ensure this, but (for instance) if
you create a new object, and
you never assign the object's reference to an instance or class variable, and
you never call a method that does this for the reference,
then the object will be thread confined.
I guess that's what want to say. Like creating a object inside the run method and not passing the reference to any other instance.
Simple example:
public String s;
public void run() {
StringBuilder sb = new StringBuilder();
sb.append("Hello ").append("world");
s = sb.toString();
}
The StringBuilder instance is thread-safe because it is confined to the thread (that executes this run method)
One way is "stack confinement" in which the object is a local variable confined to the thread's stack, so no other thread can access it. In the method below, the list is a local variable and doesn't escape from the method. The list doesn't have to be threadsafe because it is confined to the executing thread's stack. No other thread can modify it.
public String foo(Item i, Item j){
List<Item> list = new ArrayList<Item>();
list.add(i);
list.add(j);
return list.toString();
}
Another way of confining an object to a thread is through the use of a ThreadLocal variable which allows each thread to have its own copy. In the example below, each thread will have its own DateFormat object and so you don't need to worry about the fact that DateFormat is not thread-safe because it won't be accessed by multiple threads.
private static final ThreadLocal<DateFormat> df
= new ThreadLocal<DateFormat>(){
#Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyyMMdd");
}
};
Further Reading
See: http://codeidol.com/java/java-concurrency/Sharing-Objects/Thread-Confinement/
A more formal means of maintaining
thread confinement is ThreadLocal,
which allows you to associate a
per-thread value with a value-holding
object. Thread-Local provides get and
set accessormethods that maintain a
separate copy of the value for each
thread that uses it, so a get returns
the most recent value passed to set
from the currently executing thread.
It holds a copy of object per one thread, thread A can't access copy of thread B and broke it's invariants if you will do it specially (for example, assign ThreadLocal value to static variable or expose it using other methods)
That's exactly what it means. The object itself is accessed by only one thread, and is thus thread-safe. ThreadLocal objects are a kind of objects that are bound to an only thread
I means that only code running in one thread accesses the object.
When this is the case, the object doesn't need to be "thread safe"