28
Sometimes when I declare my attributes I notice the transient
and the volatile
. I have the following doubts
- The
transient
andvolatile
are access modifiers? - What is the purpose of using them?
Example:
transient String a;
volatile String b;
28
Sometimes when I declare my attributes I notice the transient
and the volatile
. I have the following doubts
transient
and volatile
are access modifiers?Example:
transient String a;
volatile String b;
40
They are not access modifiers, but modify how the Java Virtual Machine handles attributes at runtime.
A transient attribute means that it will not be serialized or deserialized along with the other attributes of a given object.
Serialization is the process in which the attributes of an object (state) are converted, one by one, into a sequence of bytes. Deserialization is the reverse process, where bytes are read and a new object is built.
The most common applications are:
You explicitly define that you do not want to serialize a particular attribute with transient
basically in the following cases:
Connection
) or any reference to a resource that needs to be opened and closed.It is also important to mention that this attribute has no effect if you overwrite the methods writeObject
and readObject
, enabling, respectively, the serialization and manual deserialization of objects.
Work with several threads It causes a lot more headaches than you can imagine. This is because often multiple threads need to access and modify shared objects.
Imagine the following scenario:
long i = 0;
void thread1() {
...
i++;
...
}
void thread2() {
...
if (i == 1) {
fazAlgo();
}
...
}
In the example, the two threads access the same variable. Assuming the reading of the thread2
occurs, in a time sequence, exactly after the increment of the thread1
, you think there might be some competition problem, considering the increment looks like an atomic operation?
A naive analysis would say that everything is fine with the threads because the two perform atomic writing and reading operations, so fazAlgo
would run smoothly.
Wrong.
Each thread can is running on a different processor. Each processor can have a cache own. Variables are read and saved first in the local cache before going to the main memory. Then, it is possible that the second thread read the old value of the variable.
The problematic scenario would occur like this:
i = 0
from the main memory and increments; the new value i = 1
is stored in the local cache, but not in the main memory.i = 0
of the main memory and does not enter the if
.Worse than that, 64-bit variables like long
and double
may have its written in memory divided by the JVM into two 32-bit cycles, which could lead to a completely corrupted reading of its values.
Such scenarios are relatively rare, but extremely difficult to identify in complex software, causing that kind of intermittent and occasional problem that ends up being swept under the carpet.
The solution, in this case, is simple:
volatile long i = 0;
A volatile attribute is guaranteed that the updated value will always be available to others threads, being recorded in the main memory as soon as updated, atomic form.
This means that whenever the value is modified in a processor, a flush to the main memory, therefore the others threads will always see the most updated value and not a possible outdated value.
Of course this is not free. Do the flush
from cache to main memory penalizes performance, after all there is a reason for hardware manufacturers to place caches on processors. It is much faster to access a register or primary cache than to access RAM.
An alternative solution would be to use synchronization methods as a block synchronized
or atomic variables such as AtomicLong
, which may be necessary when there is concurrent modification, but which are slower.
In the case of competing writing, as well remembered by Rafael in the other answer, a variable volatile
could still incur running condition as the two threads can read the same value as the main memory, and the final value would depend on which of the threads would he write last.
Interestingly, the class AtomicLong
uses volatile
:
private volatile long value;
What is the difference then? It occurs that the atomic classes use the technique known as compare and swap, that is, the variable update operation is conditioned to the old value. For example, each thread sends an instruction similar to "update the value 1 to 2". The processor then ensures that the variable will only be updated to 2
if its value is 1
, otherwise the operation fails. Let’s say the value was now 3
and the operation failed. The thread now tries again with "update the value 3 to 2" and so on until it succeeds. This technique ensures that the safe update of the value in memory.
Excellent explanation, thank you.
Considering the new answer, I believe this one will require some sort of rectification.
@Piovezan Thanks for the touch. I stepped on the ball at the time of example, it had to be modification and reading and not two same modifications. I think at the time I tried to make it very simple and it ended up being incorrect. As for the atomic increment operation, it was not my intention to confirm this in any way. It is implied in the answer that this is something that people assume, but reading the step by step execution I made it very clear that the operation is divided into read and update. Updated response!
5
Regarding the Transient is what everyone said above, I have nothing to add, however, it is necessary to keep in mind that a volatile attribute has the function of not storing caches, which ends up helping the problem of the situation below:
volatile int i = 0;
void thread1() {
i++;
}
void thread2() {
i++;
}
However, this solution does not eliminate the race condition problem, because if both threads try to increase the variable at the same time, the volatile does not prevent this value from remaining wrong. For this, it is necessary to synchronize this stretch of the increment as a critical zone.
A more appropriate use for this variable would be something like:
public class Foo extends Thread {
private volatile boolean close = false;
public void run() {
while(!close) {
// do work
}
}
public void close() {
close = true;
// interrupt here if needed
}
}
In fact the increment is not atomic. Except for local variables, which are not relevant to competition.
4
Transient:
When set to Transient it means that the field will not be serialized by java.
Post explaining better https://stackoverflow.com/questions/910374/why-does-java-have-transient-variables
Volatile:
When a field is set to volatile, this field will be viewed in a shared/updated way by all threads using this variable.
Better explanations in: http://tutorials.jenkov.com/java-concurrency/volatile.html
Could you explain it better? Anyone who doesn’t know English(like me) won’t understand much about the definitions.
Browser other questions tagged java oop
You are not signed in. Login or sign up in order to post.
Is there this in java? huahuahua has never seen it before. + 1
– user28595
There is, rs @Diegof
– DiegoAugusto