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.
Related
I have a simple code where I want to have objects generated with unique id. Here is the code snippet
public class Test {
private static long counter = 0;
private long id;
private Test() {
// Don't worry about overflow
id = counter++;
}
// Will this method always Test Object with unique id?
public static Test getTest() {
return new Test();
}
public long getId() {
return id;
}
}
Would like to know if getTest method is called by multiple threads will all TestObjects have unique id's?
It's not thread-safe because two threads can execute counter++ at same time and you can get unexpected results.
You should use AtomicInteger:
public class Test {
private static AtomicLong counter = new AtomicLong(0);
private long id;
private Test() {
// Don't worry about overflow
id = counter.incrementAndGet();
}
// Will this method always Test Object with unique id?
public static Test getTest() {
return new Test();
}
public long getId() {
return id;
}
}
No, it is not thread-safe for generating unique IDs. It may well happen that objects will receive non-unique IDs. You could use AtomicInteger/AtomicLong to make this work (i.e., private static AtomicLong counter = (new AtomicLong())) and then counter.getAndIncrement() in the constructor of Test.
The reason it is not thread-safe is that each processor/core has its own set of registers and without synchronization the variable may have inconsistent copies in the different processors/cores. Even on a single-processor system, preemptive multi-threading introduces the same problem. Synchronization would not be needed in non-preemptive threading systems.
you can also use synchronize block in your constructor if you want to lock class-level variable (Not the instance variable because for instance variable there is no need of synchronization . only one thread will be able to create object at a time).
so you can try this also as your constructor.
private Test() {
// Don't worry about overflow
synchronized(Test.class){
id = counter++;
}
}
We're building cache stores in our app backed by memory, file, and remote services. Want to avoid explicit synchronization to keep the stores simple while using decorators for behavioral concerns like blocking.
Here's a simple cache, this is just an example!
import java.util.HashMap;
public class SimpleCache {
private HashMap<String,Object> store;
private final BlockingCacheDecorator decorator;
public SimpleCache(){
store = new HashMap<String,Object>();
decorator = new BlockingCacheDecorator(this);
}
//is NOT called directly, always uses decorator
public Object get(String key){
return store.get(key);
}
//is NOT called directly, always uses decorator
public void set(String key, Object value){
store.put(key, value);
}
//is NOT called directly, always uses decorator
public boolean isKeyStale(String key){
return !(store.containsKey(key));
}
//is NOT called directly, always uses decorator
public void refreshKey(String key){
store.put(key, new Object());
}
public BlockingCacheDecorator getDecorator(){
return decorator;
}
}
getDecorator() returns a decorator providing synchronization for get() and set(), while isKeyStale() and refreshKey() allows the decorator to check if a key should be refreshed without knowing why or how. I got the idea for a synchronizing decorator from here.
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class BlockingCacheDecorator {
private SimpleCache delegate;
private final ReentrantReadWriteLock lock;
public BlockingCacheDecorator(SimpleCache cache){
delegate = cache;
lock = new ReentrantReadWriteLock();
}
public Object get(String key){
validateKey(key);
lockForReading();
try{
return delegate.get(key);
}finally{ readUnlocked(); }
}
public void setKey(String key, Object value){
lockForWriting();
try{
delegate.set(key,value);
}finally{ writeUnlocked(); }
}
protected void validateKey(String key){
if(delegate.isKeyStale(key)){
try{
lockForWriting();
if(delegate.isKeyStale(key))
delegate.refreshKey(key);
}finally{ writeUnlocked(); }
}
}
protected void lockForReading(){
lock.readLock().lock();
}
protected void readUnlocked(){
lock.readLock().unlock();
}
protected void lockForWriting(){
lock.writeLock().lock();
}
protected void writeUnlocked(){
lock.writeLock().unlock();
}
}
Questions:
Assuming SimpleCache is only ever used via its decorator, is the code thread-safe?
Is it bad practice for ReadWriteLock to be declared outside the class being synchronized? SimpleCache.getDecorator() ensures a 1-to-1 mapping between cache and decorator instances, so I'm assuming this is ok.
Is this code thread-safe?
Yes. Assuming that the instance of the decorated SimpleCache is not passed about.
Is it bad practice for ReadWriteLock to be declared outside the class being synchronized? SimpleCache.getDecorator() ensures a 1-to-1 mapping between cache and decorator instances, so I'm assuming this is ok.
No. Although it is also worth noting that as discussed in comments, BlockingCacheDecorator would usually implement a Cache interface.
In its current form the code is trivially non-threadsafe, as there's nothing preventing a caller from calling methods of SimpleCache directly, or indeed pass the same SimpleCache instance to multiple decorators, causing even more mayhem.
If you promise never to do that, it is technically thread-safe, but we all know how much those promises are worth.
If the aim is to be able to use different implementations of underlying caches, I'd create a CacheFactory interface:
interface CacheFactory {
Cache newCache();
}
A sample implementation of the factory:
class SimpleCacheFactory implements CacheFactory {
private final String cacheName; //example cache parameter
public SimpleCacheFactory( String cacheName ) {
this.cacheName = cacheName;
}
public Cache newCache() {
return new SimpleCache( cacheName );
}
}
And finally your delegate class:
public class BlockingCacheDecorator {
private final Cache delegate;
private final ReentrantReadWriteLock lock;
public BlockingCacheDecorator(CacheFactory factory){
delegate = factory.newCache();
lock = new ReentrantReadWriteLock();
}
//rest of the code stays the same
}
This way there's a much stronger guarantee that your Cache instances won't be inadvertently reused or accessed by an external agent. (That is, unless the factory is deliberately mis-implemented, but at least your intention not to reuse Cache instances is clear.)
Note: you can also use an anonymous inner class (or possibly a closure) to provide the factory implementation.
Let's say I have the following,
public class Foo{
private String bar;
public String getBar(){
return bar;
}
public void setBar(String bar){
this.bar = bar;
}
}
Are these methods automatically threadsafe due to the immutable nature of the String class, or is some locking mechanism required?
No, this is not threadsafe. Foo is mutable, so if you want to ensure that different threads see the same value of bar – that is, consistency – either:
Make bar volatile, or
Make the methods synchronized, or
Use an AtomicReference<String>.
The reads and writes of bar are themselves atomic, but atomicity is not thread safety.
http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html
For in-depth coverage of Java concurrency, grab a copy of Java Concurrency in Practice (aka JCIP).
You're setting references, and as such String's immutability doesn't come into play. You're not affecting the contents of String.
No, not safe.
This is Foo mutable behavior; String's immutability does not accrue to Foo.
public class Foo{
private String bar;
public synchronized String getBar(){
return bar;
}
public synchronized void setBar(String bar){
this.bar = bar;
}
}
No, it's not thread safe.
While String is immutable, the issue comes from the field of Foo. To make this more apparent, consider for example a method whose job would be to append (rather than replace) the value of bar. When it's called from multiple threads, some writes could be lost. The same (lost writes) can happen with your simple setter too, even if it's not obvious initially in this case.
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.
Consider the following code:
public class Foo {
private static final Object LOCK = new Object();
private Object _lockRef1 = LOCK;
private Object _lockRef2 = LOCK;
private int _indx = 0;
public void dec() {
synchronized(_lockRef1) {
_indx--;
}
}
public void inc() {
synchronized(_lockRef2) {
_indx++;
}
}
}
Is call to methods dec() and inc() threadsafe? On the one hand these methods are synchronized on two different instances _lockRef1 and _lockRef2. On the other hand, these instances "point" on the same object LOCK...
They're not "synchronized on two different instances" - just because you use two different variables doesn't mean there are two different instances. You've got several variables each of which will have the same value - a reference to the single instance of java.lang.Object.
So yes, this is thread-safe. Of course you shouldn't write code like this in terms of readability, but assuming you're just trying to understand what happens, it's fine.