Let's say we have very simple Java class MyClass.
public class MyClass {
private int number;
public MyClass(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
There are three ways to construct thread-safe Java class which has some state:
Make it truly immutable
public class MyClass {
private final int number;
public MyClass(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
}
Make field number volatile.
public class MyClass {
private volatile int number;
public MyClass(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
Use a synchronized block. Classic version of this approach described in Chapter 4.3.5 of Java Concurrency in practice. And the funny thing about that it has an error in the example which is mentioned in a errata for this book.
public class MyClass {
private int number;
public MyClass(int number) {
setNumber(number);
}
public synchronized int getNumber() {
return number;
}
public synchronized void setNumber(int number) {
this.number = number;
}
}
There is one more fact that should be added to the context of discussion. In a multhithreaded environment JVM is free to reorder instructions outside of synchronized block preserving a logical sequence and happens-before relationships specified by JVM. It may cause publishing object which is not properly constructed yet to another thread.
I've got a couple of questions regarding the third case.
Will it be equivalent to a following piece of code:
public class MyClass {
private int number;
public MyClass(int number) {
synchronized (this){
this.number = number;
}
}
public synchronized int getNumber() {
return number;
}
public synchronized void setNumber(int number) {
this.number = number;
}
}
Will a reordering be prevented in the third case or it possible for JVM to reorder intstructions and therefore publish object with default value in field number?
If an answer for the second question is yes than I have one more question.
public class MyClass {
private int number;
public MyClass(int number) {
synchronized (new Object()){
this.number = number;
}
}
public synchronized int getNumber() {
return number;
}
public synchronized void setNumber(int number) {
this.number = number;
}
}
This strange-looking synchronized (new Object()) is supposed to prevent reordering effect. Will it work?
Just to be clear, all these examples don't have any practical applications. I'm just curious about nuances of multithreading.
synchronized(new Object()) will do nothing, since synchronization is only on the object you synchronize on. So if thread A synchronizes on oneObject, and thread B synchronizes on anotherObject, there is no happens-before between them. Since we can know for a fact that no other thread will ever synchronize on the new Object() you create there, this won't establish a happens-before between any other thread.
Regarding your synchronzied in the constructor, if your object is safely published to another thread, you don't need it; and if it's not, you're probably in a mess of trouble as it is. I asked this question on the concurrency-interest list a bit ago, and an interesting thread resulted. See in particular this email, which points out that even with your constructor synchronized, in the absence of safe publication another thread could see default values in your fields, and this email which (imho) ties the whole thing together.
In question #3, synchronized(new Object()) is a no-op and will prevent nothing. The compiler can determine that no other threads could possibly synchronize on that object (since nothing else can access the object.) This is an explicit example in Brian Goetz's paper "Java theory and practice: Synchronization optimizations in Mustang".
Even if you did need to synchronize in a constructor, and even if your synchronized(new Object()) block was useful - ie, you were synchronizing on a different long-lived object, since your other methods are synchronizing on this, you have visibility problems if you're not synchronizing on the same variable. That is to say, you do indeed want your constructor to also use synchronized(this).
An aside:
Synchronizing on this is considered poor form. Instead, synchronize on some private final field. Callers may synchronize on your object, which could lead to a deadlock. Consider the following:
public class Foo
{
private int value;
public synchronized int getValue() { return value; }
public synchronized void setValue(int value) { this.value = value; }
}
public class Bar
{
public static void deadlock()
{
final Foo foo = new Foo();
synchronized(foo)
{
Thread t = new Thread() { public void run() { foo.setValue(1); } };
t.start();
t.join();
}
}
}
It's not obvious to callers of the Foo class that this would deadlock. Best to keep your locking semantics internal and private to your class.
Related
I know that final instance-variables are published safely to all threads, after the constructor is finished. However, I wonder whether this is still safe, if the final instance-variable contains a reference to an object that contains a non-final instance-variable. This secondary, non-final instance-variable is never changed after the constructor is done. Consider the following example:
public class NonFinalImmutable {
private Iterable<String> list = Collections.unmodifiableList(Arrays
.asList("foo", "bar", "foobar"));
public Iterable<String> getList() {
return list;
}
}
public class FinalImmutable {
private final NonFinalImmutable reference;
private final String[] array;
public FinalImmutable(NonFinalImmutable reference,
String... arrayEntries) {
this.reference = reference;
this.array = arrayEntries;
}
public NonFinalImmutable getReference() {
return reference;
}
public String[] getArray() {
return array;
}
}
private void execute() {
new Thread() {
#Override
public void run() {
useLater(construct());
}
}.start();
}
private FinalImmutable construct() {
return new FinalImmutable(new NonFinalImmutable(), "asdf", "jklö");
}
private void useLater(FinalImmutable finalImmutable) {
new Thread() {
#Override
public void run() {
for (String s : finalImmutable.getReference().getList()) {
System.out.println(s);
}
System.out.println();
for (String s : finalImmutable.getArray()) {
System.out.println(s);
}
}
}.start();
}
Is it safe to use the contents of the instance-variables FinalImmutable.reference and FinalImmutable.array in another thread even though they contain non-final instance-variables?
Yes, there is a freeze-action which occurs when assigning final fields. You should read Aleksey Shipilëv's blog it's really useful. He discusses the freeze action semantics in a 2014 blog entry
And here is how it is formally specified. Notice that w may not be the write of final field, and r2 is not the read of the final field. What really matters is that the subchain containing freeze action F, some action a, and r1 which reads the final field — all together make r2 observe w.
Notice two new orders, dereference order, and memory
In the blog he proves that a write of final field happens before some action which in turn happens before a subsequent non-final field read r2.
Also in your example, since you first construct the a non-shared NonFinalImmutable the final assignment should freeze the writes occurred prior. If the NonFinalImmutable was accessible outside, all bets are off.
I was wondering if there was an easier way to increment another class's private variables. Here is how I generally would go about it:
If I only need to do this rarely in my code:
pc.setActionsCurrent(pc.getActionsCurrent()-1);
If I need to do lots of incrementing, I would just make a special setter:
//In the PC class
public void spendAction(){
this.actionsCurrent--;
}
//In the incrementing Class
pc.spendAction();
Is there a better way to go about this? If the variable were public
pc.actionsCurrent--;
would be enough, and I can't help but feel I'm over-complicating things.
No. The method abstraction is generally the way to go about it, you might also pass in the increment value (and you can leverage that in your implementation). Consider something like
private long increment = 1;
private long myVariable = 0;
public void setMyVariable(long myVariable) {
this.myVariable = myVariable;
}
public void setIncrement(long increment) {
this.increment = increment;
}
public long getMyVariable() {
return this.myVariable;
}
public void addToMyVariable(long val) {
this.myVariable += val;
}
public void incrementMyVariable() {
addToMyVariable(increment);
}
The above would allow the increment value to vary (and this is generally called encapsulation).
Just define an increment method. For generality you could supply the increment as a parameter, and it could be negative:
public void increment(int augend)
{
this.actionsCurrent += augend;
}
If I have a an object with an attribute private int i;, I know I can make the getter and setter methods "synchronized" like so ... But since it's possible another method might be added later that accesses/changes i directly, is there any way to declare that i is a "synchronized" attribute?
public class SharedObject {
int i;
synchronized public int getI() {
return i;
}
synchronized public void setI(int i) {
this.i = i;
}
public void badMethod() { <<-- added at later date by forgetful programmer
// accidentally messes up 'i' because method is not "synchronized" !!
}
}
I thought maybe this could work, but it didn't:
public class SharedObject {
synchronized int i; <<-- this won't compile
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public void badMethod() {
// cannot mess up 'i', because 'i' is declared as 'synchronized'
}
}
There is no way to declare a member variable as synchronized.
However, if i represents independent state of the object -- in other words if i can be set and get independently of other state and you're not depending on the synchronization of the getter and setter of i to serialize access with other synchronized methods, then you can declare i as volatile.
You could consider moving all concurrency-critical code to its own class (and even declare the class final) which might perhaps make the intent more clear. But if a "forgetful programmer" can make changes to the source code, there is nothing to prevent any sort of error from being introduced.
Let's say I have the following class that will be read heavily, but only written to occasionally. It will be used in a multi-threaded web app, so it needs to be thread safe:
public class Foo {
private volatile String foo;
public String getFoo() {
return foo;
}
public synchronized String setFoo(String in) {
this.foo = in;
}
}
Java Concurrency (http://www.ibm.com/developerworks/java/library/j-jtp06197/index.html) states that this is a fragile way to protect write access while improving read access. What is a stronger alternative to this pattern? Or any alternative if foo will need to mutable in a read-heavy environment? Thank you.
Volatile provides fast thread-safe lock-free access to a field without synchronization
private volatile String foo;
public String getFoo() {
return foo;
}
public void setFoo(String in) {
this.foo = in;
}
volatile solves 3 problems 1) memory visibility 2) atomic writes for double and long fields 3) forbids instructions reordering. But it's not enough if you need several operations over a field as one atomic transaction, such as increment. This code is broken
private volatile int id;
public void incrementId() {
id++;
}
because if 2 threads simulataneously read and increment it and save the result then the result of the first increment will be overwritten with the result of the second increment. To prevent this from happening we need to use synchronization
private int id;
public synchronized int nextId() {
return ++id;
}
or java.util.concurrent.atomic package
private AtomicInteger id = new AtomicInteger();
public void incrementId() {
return id.incrementAndGet();
}
If all you are doing is setting foo, then you don't need to synchronize the method. making the reference volatile is sufficient.
At the link you said there is this code for "infrequent updates" usage:
#ThreadSafe
public class CheesyCounter {
// Employs the cheap read-write lock trick
// All mutative operations MUST be done with the 'this' lock held
#GuardedBy("this") private volatile int value;
public int getValue() { return value; }
public synchronized int increment() {
return value++;
}
}
The increment method is only using synchronized because it is doing more than just setting the value of value as stated in the description, if all you are doing is this.foo = in; that is atomic.
In the text the "fragility of this pattern" means things can get messy very fast when you mix volatile and other synchronization methods to do more than just simple examples.
See package java.util.concurrent.locks for the interfaces Condition and Lock and the class ReentrantLock. I think that, and using synchronized is what the author means by "stronger alternatives". You should also see Object.wait, Object.notify and Object.notifyAll if you don't know that yet.
I have thread safe double checked Singleton class that holds a LinkedList with get/set/size methods in the Singleton class. Then I have simple pool class that is using this Singleton class to manage pool of objects.
My question is how can I defend the methods of get/set both in the singleton and the pool class without using sync methods. Here's my code
public class SingletonDoubleCheckedLockingPattern {
private static SingletonDoubleCheckedLockingPattern s = new SingletonDoubleCheckedLockingPattern();
private LinkedList<Object> linkedList;
public int GetListObjectCount() {
return linkedList.size();
}
public Object GetObjectFromList() {
return linkedList.poll();
}
public void SetObjectFromList(Object ee) {
linkedList.add(ee);
}
private SingletonDoubleCheckedLockingPattern() {
linkedList = new LinkedList<Object>();
}
/**
* SingletonHolder is loaded on the first execution of
* Singleton.getInstance() or the first access to SingletonHolder.INSTANCE,
* not before.
*/
private static class SingletonHolder {
public static final SingletonDoubleCheckedLockingPattern INSTANCE = new SingletonDoubleCheckedLockingPattern();
}
public static SingletonDoubleCheckedLockingPattern getInstance() {
return SingletonHolder.INSTANCE;
}
// avoid cloning
public final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}
public class SingletonObjectPool {
private int maxlistValue = 10;
public Object GetObject()
{
int listCount = SingletonDoubleCheckedLockingPattern.getInstance().GetListObjectCount();
if(listCount > 0)
{
return SingletonDoubleCheckedLockingPattern.getInstance().GetObjectFromList();
}
return null;
}
public void SetObject()
{
int listCount = SingletonDoubleCheckedLockingPattern.getInstance().GetListObjectCount();
if(listCount < maxlistValue)
{
SingletonDoubleCheckedLockingPattern.getInstance().SetObjectFromList(new Object());
}
}
}
You could use a BlockingQueue which is thread safe. You shouldn't need to check whether a collection is empty before attempting to remove an element, the collection has a method to do this.
To simplify your code and make it thread safe you can do.
public class SingletonObjectPool {
private static final int maxlistValue = 10;
private static final BlockingQueue queue
= new ArrayBlockingQueue(maxListValue);
public static Object getObject() {
return queue.poll();
}
public static void addObjectAsRequired() {
queue.offer(new Object());
}
}
The only way I can think that you can possibly call methods such as GetListObjectCount without using synchronized, is if the list itself is thread-safe and will behave sensibly when this method is called in the face of concurrent modifications.
In that case, there won't be any other problems, as the reference to the list itself never changes. You may want to declare it as final to make this abundantly clear, and to have the compiler warn anyone who tries to reassign the list. (If this were a requirement, the reference would need to be volatile at the very least, but it opens up lots of other questions in the correctness of multiple operations of your class).
The bottom line is that "thread safety" is not a simple, binary concept. You can't just say a particular class and/or method is thread-safe; rather, it's about what combinations of methods you can call with useful and correct semantics.