This honestly compiles and runs in Java 7
Just what the question says - while it is technically legal to do so, if you call synchronized on some method variable, does it actually achieve anything? Or is it, because method variables exist within their own little world, going to fail to achieve anything worthwhile?
eg:
public int getX(){
Integer k = 12;
synchronized (k) {
System.out.println("meow");
}
return x;
}
You're asking the wrong question. Whether the variable is local is irrelevant, as shown in the following example:
class Test {
private Map<String, String> map = new HashMap<>();
public void put(String key, String value) {
Map<String, String> localMap = this.map;
synchronized (localMap) {
localMap.put(key, value);
}
}
}
The local reference is actually necessary if there's a possibility that the field could be replaced while you're in the synchronized block.
So the real question is whether you should ever lock on a private value, that is, an object not available to other threads. You may think your example demonstrates such a case, but per the JLS, the autoboxed Integer 12 is cached, meaning you're actually synchronizing on a global value.
Now, assuming you have a local value that's actually private to its thread, there's generally no point in synchronizing on it, and I think some analyzers will warn you if you try. However, see here and here for a possible exception.
Related
In the book "Java Concurrency in Practice" the following code is attached:
public class Counter {
private long value = 0;
public synchronized long getValue() {
return value;
}
public synchronized void increment() {
++value;
}
}
Here is the value field with type long, as well as synchronized read and increment methods.
Do I understand correctly that the synchronization of the read method is needed only for the long and double types, because they are not atomic? And if the field value is of type int, synchronization of the read method will be unnecessary?
You need to synchronize the getValue method.
In Java, the synchronized keyword gives you both visibility and atomicity guarantees. As a rule of thumb, you should remember that the compiler developers and CPU vendors are free to do optimizations such as memory reordering or caching variables in registers as long as the behavior of the optimized program remains unchanged in a single-threaded environment.
Now let's see what happens when different threads call the getValue and increment methods, and the getValue is no longer synchronized. From the perspective of JVM, any thread that only reads the value and never updates it through the increment method is effectively always reading the same constant value. So inside the reader thread, JVM might choose to save the variable in a register and never read it from memory again!
As the comments have suggested, the synchronized keyword can be removed by changing the type of value from an int to AtomicInteger. But even if you don't want to use an AtomicInteger, you can rewrite your class like this:
public class Counter {
private volatile int value = 0;
public int getValue() {
return value;
}
public synchronized void increment() {
++value;
}
}
The volatile keyword will ensure visibility, and the reads no longer require any locking. I suggest checking these references to learn more about Java Memory Model:
https://jenkov.com/tutorials/java-concurrency/index.html
https://docs.oracle.com/javase/specs/jls/se17/html/jls-17.html
Lets say I have a code like this in my servlet:
private static final String RESOURCE_URL_PATTERN = "resourceUrlPattern";
private static final String PARAM_SEPARATOR = "|";
private List<String> resourcePatterns;
#Override
public void init() throws ServletException {
String resourcePatterns = getInitParameter(RESOURCE_URL_PATTERN);
this.resourcePatterns = com.google.common.base.Splitter.on(PARAM_SEPARATOR).trimResults().splitToList(resourcePatterns);
}
Is this thread safe to use 'resourcePatterns' if it will never be modified?
Lets say like this:
private boolean isValidRequest(String servletPath) {
for (String resourcePattern : resourcePatterns) {
if (servletPath.matches(resourcePattern)) {
return true;
}
}
return false;
}
Should I use CopyOnWriteArrayList or ArrayList is OK in this case?
Yes, List is fine to read from multiple threads concurrently, so long as nothing's writing.
For more detailed information on this, please see this answer that explains this further. There are some important gotchas.
From java concurrency in practice we have:
To publish an object safely, both the reference to the object and the
object's state must be made visible to other threads at the same time.
A properly constructed object can be safely published by:
Initializing an object reference from a static initializer. Storing a
reference to it into a volatile field. Storing a reference to it into
a final field. Storing a reference to it into a field that is properly
guarded by a (synchronized) lock.
your list is neither of these. I suggest making it final as this will make your object effectively immutable which in this case would be enough. If init() is called several times you should make it volatile instead. With this I of course assume that NO changes to the element of the list occur and that you don't expose any elements of the list either (as in a getElementAtPosition(int pos) method or the like.
http://www.javapractices.com/topic/TopicAction.do?Id=29
Above is the article which i am looking at. Immutable objects greatly simplify your program, since they:
allow hashCode to use lazy initialization, and to cache its return value
Can anyone explain me what the author is trying to say on the above
line.
Is my class immutable if its marked final and its instance variable
still not final and vice-versa my instance variables being final and class being normal.
As explained by others, because the state of the object won't change the hashcode can be calculated only once.
The easy solution is to precalculate it in the constructor and place the result in a final variable (which guarantees thread safety).
If you want to have a lazy calculation (hashcode only calculated if needed) it is a little more tricky if you want to keep the thread safety characteristics of your immutable objects.
The simplest way is to declare a private volatile int hash; and run the calculation if it is 0. You will get laziness except for objects whose hashcode really is 0 (1 in 4 billion if your hash method is well distributed).
Alternatively you could couple it with a volatile boolean but need to be careful about the order in which you update the two variables.
Finally for extra performance, you can use the methodology used by the String class which uses an extra local variable for the calculation, allowing to get rid of the volatile keyword while guaranteeing correctness. This last method is error prone if you don't fully understand why it is done the way it is done...
If your object is immutable it can't change it's state and therefore it's hashcode can't change. That allows you to calculate the value once you need it and to cache the value since it will always stay the same. It's in fact a very bad idea to implement your own hasCode function based on mutable state since e.g. HashMap assumes that the hash can't change and it will break if it does change.
The benefit of lazy initialization is that hashcode calculation is delayed until it is required. Many object don't need it at all so you save some calculations. Especially expensive hash calculations like on long Strings benefit from that.
class FinalObject {
private final int a, b;
public FinalObject(int value1, int value2) {
a = value1;
b = value2;
}
// not calculated at the beginning - lazy once required
private int hashCode;
#Override
public int hashCode() {
int h = hashCode; // read
if (h == 0) {
h = a + b; // calculation
hashCode = h; // write
}
return h; // return local variable instead of second read
}
}
Edit: as pointed out by #assylias, using unsynchronized / non volatile code is only guaranteed to work if there is only 1 read of hashCode because every consecutive read of that field could return 0 even though the first read could already see a different value. Above version fixes the problem.
Edit2: replaced with more obvious version, slightly less code but roughly equivalent in bytecode
public int hashCode() {
int h = hashCode; // only read
return h != 0 ? h : (hashCode = a + b);
// ^- just a (racy) write to hashCode, no read
}
What that line means is, since the object is immutable, then the hashCode has to only be computed once. Further, it doesn't have to be computed when the object is constructed - it only has to be computed when the function is first called. If the object's hashCode is never used then it is never computed. So the hashCode function can look something like this:
#Override public int hashCode(){
synchronized (this) {
if (!this.computedHashCode) {
this.hashCode = expensiveComputation();
this.computedHashCode = true;
}
}
return this.hashCode;
}
And to add to other answers.
Immutable object cannot be changed. The final keyword works for basic data types such as int. But for custom objects it doesn't mean that - it has to be done internally in your implementation:
The following code would result in a compilation error, because you are trying to change a final reference/pointer to an object.
final MyClass m = new MyClass();
m = new MyClass();
However this code would work.
final MyClass m = new MyClass();
m.changeX();
If a public method of an object only uses parameters passed, and local variables, then
can we say that it is thread-safe?
A so called pure function is indeed thread safe, but only if there are absolutely no side effects (ie, objects passed in via parameters altered).
If local memeber variables are not modified and the state of passed parameters is not changed (i.e. via methods on those parameters), then it is thread safe.
Furthermore, if passed parameters are objects, making them final does not guarantee thread safety.
public class Foo{
private int count = 1;
public void incrementFoo(){
count += 1;
}
public int getFoo(){
return count;
}
}
private int multiplier = 5;
//Not safe
public static int calculateFoo(final Foo myFoo){
//you can still do this, even if myFoo is final
myFoo.incrementFoo();
return myFoo.getFoo() * multiplier;
}
Yes, it's thread safe. It can not interfere with invocations of other methods. (Unless it has some other nasty side effects.)
Any interleaving of the instructions of this method, and the instructions of any other method will be ok.
It depends. There are ways it can easily be not thread safe.
First, if any argument that is passed into the method is not thread safe and your method uses it in a multi-threaded manner without proper synchronization, it is not thread safe. For example,
// HashMap is not thread safe
public void foo(String key, HashMap<String,String> map) {
String value = map.get(key);
if (value == null) {
map.put(key, "new value");
}
}
Another possibility is if any object that was created within the method escapes the method. Consider the following:
public void foo() {
Map map = ...; // create and populate the map
ListenerQueue.getQueue().add(map); // there are listener threads waiting on this queue
// do some other work
}
If there are other threads that are waiting on this queue and start using the map object, then the map object has escaped, and is subject to the same thread-safety issues.
Say you have the following class
public class AccessStatistics {
private final int noPages, noErrors;
public AccessStatistics(int noPages, int noErrors) {
this.noPages = noPages;
this.noErrors = noErrors;
}
public int getNoPages() { return noPages; }
public int getNoErrors() { return noErrors; }
}
and you execute the following code
private AtomicReference<AccessStatistics> stats =
new AtomicReference<AccessStatistics>(new AccessStatistics(0, 0));
public void incrementPageCount(boolean wasError) {
AccessStatistics prev, newValue;
do {
prev = stats.get();
int noPages = prev.getNoPages() + 1;
int noErrors = prev.getNoErrors;
if (wasError) {
noErrors++;
}
newValue = new AccessStatistics(noPages, noErrors);
} while (!stats.compareAndSet(prev, newValue));
}
In the last line while (!stats.compareAndSet(prev, newValue)) how does the compareAndSet method determine equality between prev and newValue? Is the AccessStatistics class required to implement an equals() method? If not, why? The javadoc states the following for AtomicReference.compareAndSet
Atomically sets the value to the given updated value if the current value == the expected value.
... but this assertion seems very general and the tutorials i've read on AtomicReference never suggest implementing an equals() for a class wrapped in an AtomicReference.
If classes wrapped in AtomicReference are required to implement equals() then for objects more complex than AccessStatistics I'm thinking it may be faster to synchronize methods that update the object and not use AtomicReference.
It compares the refrerences exactly as if you had used the == operator. That means that the references must be pointing to the same instance. Object.equals() is not used.
Actually, it does not compare prev and newValue!
Instead it compares the value stored within stats to prev and only when those are the same, it updates the value stored within stats to newValue. As said above it uses the equals operator (==) to do so. This means that anly when prev is pointing to the same object as is stored in stats will stats be updated.
It simply checks the object reference equality (aka ==), so if object reference held by AtomicReference had changed after you got the reference, it won't change the reference, so you'll have to start over.
Following are some of the source code of AtomicReference. AtomicReference refers to an object reference. This reference is a volatile member variable in the AtomicReference instance as below.
private volatile V value;
get() simply returns the latest value of the variable (as volatiles do in a "happens before" manner).
public final V get()
Following is the most important method of AtomicReference.
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
The compareAndSet(expect,update) method calls the compareAndSwapObject() method of the unsafe class of Java. This method call of unsafe invokes the native call, which invokes a single instruction to the processor. "expect" and "update" each reference an object.
If and only if the AtomicReference instance member variable "value" refers to the same object is referred to by "expect", "update" is assigned to this instance variable now, and "true" is returned. Or else, false is returned. The whole thing is done atomically. No other thread can intercept in between. As this is a single processor operation (magic of modern computer architecture), it's often faster than using a synchronized block. But remember that when multiple variables need to be updated atomically, AtomicReference won't help.
I would like to add a full fledged running code, which can be run in eclipse. It would clear many confusion. Here 22 users (MyTh threads) are trying to book 20 seats. Following is the code snippet followed by the full code.
Code snippet where 22 users are trying to book 20 seats.
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread[] ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
Following is the github link for those who wants to see the running full code which is small and concise.
https://github.com/sankar4git/atomicReference/blob/master/Solution.java