Sun Proprietary/Confidential: Internal Use Only 1 Multi-Threading Primer Byron Nevins December 10, 2007
Sun Proprietary/Confidential: Internal Use Only 2 Multi-Threading Primer One famous example. If you completely understand this example you will be well on your way to understanding most multi-threading issues.
Sun Proprietary/Confidential: Internal Use Only 3 Multi-Threading Primer Class Foo { private static int i = -1; public static int getInt() { if(i < 0) { i += 5; } return i; } What's wrong with this code? Answer: ● Nothing if it is single-threaded code. ● Plenty if it is multi-threaded code
Sun Proprietary/Confidential: Internal Use Only 4 Multi-Threading Primer Class Foo { private static int i = -1; public static int getInt() { if(i < 0) { synchronized(Foo.class) { if(i < 0) i += 5; } return i; } This is the infamous Double Checked Lock idiom ● Is it possible for getInt() to return anything other than 4? ● Does this work perfectly in a multi-threaded environment? ● If so – what's the problem with Double Checked Lock?
Sun Proprietary/Confidential: Internal Use Only 5 Multi-Threading Primer Class Foo { private static Foo instance = null; private boolean peace; public boolean getPeace() { return peace; } private Foo() { peace = true;} public static Foo getFoo() { if(instance == null) { synchronized(Foo.class) { if(instance == null) instance = new Foo(); } return instance; } This is the infamous Double Checked Lock idiom again. ● Is it possible for getFoo() to return anything other than a properly constructed Foo? ● Is it possible that more than one Foo instance can ever exist? ● Does this work perfectly in a multi-threaded environment? ● If so – what's the problem with Double Checked Lock?
Sun Proprietary/Confidential: Internal Use Only 6 Multi-Threading Primer class NuclearWeaponManager { public void killEveryoneIfNoPeace() { Foo foo = Foo.getFoo(); if(foo.getPeace() == false) launchAllOutNuclearWar(); } We should all live to see another day as long as Foo.getFoo() absolutely positively for sure returns a properly constructed Foo instance. See the next slide for the final result of the Double Checked Idiom in a multi-threaded environment.
Sun Proprietary/Confidential: Internal Use Only 7 Multi-Threading Primer OOPS!!! !
Sun Proprietary/Confidential: Internal Use Only 8 Multi-Threading Primer The Java Memory Model, like Quantum Mechanics is spooky and not obvious. Java has much much better performance with Multi-Threading than the old days. High Performance always exacts its tribute – which is super-complex code. Luckily we don't need to know this super-complex code, we just need to know a few simple principles
Sun Proprietary/Confidential: Internal Use Only 9 Multi-Threading Primer There are 2 main aspects of writing thread-safe code: ● Mutual Exclusion ● Visibility Things that can only be done by one thread need to be in a synchronized block. The JVM will guarantee that one and only one thread can enter the block at once. There is no guarantee of “seeing” changes to a mutable variable done by one thread in another thread unless all access to the variable is protected by synchronized blocks. E.g. You can not have a thread-safe program if a variable is “written” in a synchronized block and is “read” without synchronization.
Sun Proprietary/Confidential: Internal Use Only 10 Multi-Threading Primer A Quote from our Hero You may hear it said that to improve performance, you should avoid the use of synchronization when reading or writing atomic data. This advice is dangerously wrong. -- Joshua Bloch
Sun Proprietary/Confidential: Internal Use Only 11 Multi-Threading Primer Next Time: What's volatile and why should I care? What's a deadlock? How can I prevent it? What's a livelock? Is that bad?
Sun Proprietary/Confidential: Internal Use Only 12 Multi-Threading Primer Q & A