8
Steven Seida Singleton Fun

Steven Seida

Embed Size (px)

DESCRIPTION

Singleton Fun. Steven Seida. Multi-Threading Problem. public class Foo { private Foo myInstance; private Foo() {} … public static Foo getInstance() { if (myInstance==null) { myInstance = new Foo(); } } } //class foo. Result is Multiple Instances. Time Step --1-- --2-- - PowerPoint PPT Presentation

Citation preview

Page 1: Steven Seida

Steven Seida

Singleton Fun

Page 2: Steven Seida

Multi-Threading Problem

public class Foo {private Foo myInstance;private Foo() {}…public static Foo getInstance() {

if (myInstance==null) {myInstance = new Foo();

}}

} //class foo

Process #1public static Foo getInstance() {

if (myInstance==null) {myInstance = new

Foo(); }

Process #2public static Foo getInstance() {

if (myInstance==null) {

myInstance = new Foo(); }

Time Step--1----2----3----4----5--

Result is Multiple Instances

Page 3: Steven Seida

Simple Fix – Synchronized Method

public class Foo {private Foo myInstance;private Foo() {}…public static synchronized Foo getInstance() {

if (myInstance==null) {myInstance = new Foo();

}}…

} //class foo

• Causes blocking around any calls to getInstance()– Works but may be more costly than we can afford.

No two threads may enter the method at the same time.

Page 4: Steven Seida

Improve Multi-Threading Option 1

Need to lock on creation of the variable, rather than an entire method.

public class Foo {private static Foo myInstance = new Foo();private Foo() {}…public static Foo getInstance() {

myInstance = new Foo();}…

} //class foo

Greedy initialization is guaranteed to be thread safe.

Page 5: Steven Seida

Improve Multi-Threading Option 2

Need to lock on creation of the variable, rather than an entire method.

public class Foo {private volatile static Foo myInstance;private Foo() {}…public static Foo getInstance() {

if (myInstance == null) {synchronized (Foo.class) {

if (myInstance == null) {myInstance = new Foo();

}}

}return myInstance;

}…

} //class foo

Never cached thread-locally – always writes/read with ‘main memory’.

Only synchronize the first time through.

Confirm someone else didn’t beat you here.

Page 6: Steven Seida

Volatile and Synchronized*

Declaring a volatile Java variable means: The value of this variable will never be cached thread-locally: all reads

and writes will go straight to "main memory";

Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.

We say "acts as though" in the second point, because to the programmer at least (and probably in most JVM implementations) there is no actual lock object involved.

*http://www.javamex.com/tutorials/synchronization_volatile.shtml#

Applicable to Java 5 and later

Page 7: Steven Seida

Characteristic Synchronized Volatile

Type of variable Object Object or primitive

Null allowed? No Yes

Can block? Yes No

All cached variables synchronized on access?

Yes From Java 5 onwards

When synchronization happens

When you explicitly enter/exit a synchronized block

Whenever a volatile variable is accessed.

Can be used to combined several operations into an atomic operation?

Yes PreJava 5, no. Atomic get/set of volatiles possible in Java 5.

Comparison of Synchronized and Volatile

Page 8: Steven Seida

Synchronized vs Volatile

In other words, the main differences between synchronized and volatile are:

• a primitive variable may be declared volatile (whereas you can't synchronize on a primitive with synchronized);

• an access to a volatile variable never has the potential to block: we're only ever doing a simple read or write, so unlike a synchronized block we will never hold on to any lock;

• because accessing a volatile variable never holds a lock, it is not suitable for cases where we want to read-update-write as an atomic operation (unless we're prepared to "miss an update");

• a volatile variable that is an object reference may be null (because you're effectively synchronizing on the reference, not the actual object).

Note: Attempting to synchronize on a null object will throw a NullPointerException.