Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
 
Notes on Concurrent, parallel programming with threads Concurrent = work done in several computational processes, only requires one CPU Parallel = work (computations) done simultaneous, requires multiple CPU:s – locally or distributed
GC and Threads and Java CG made easy in Java Person p = null; Concurrent programming made possible (but not easy) Low level support: threads and mutexes volatile boolean stop = false; public void stop() { stop = true; } public void run() { while(!stop) { try { // Do some work Thread.sleep(10); // check stop }catch(InterruptedException ie) { // Ignore } } } // stop = true; thread.interrupt();
Some Hard stuff Data  visibility  between threads Volitile semantics Asynchronous code Race conditions and Deadlocks Congestion/Performance
Data visibility Data not guaranteed to be visable between threads without synchronization long and double not even guaranteed to be ”complete” // In thread 1 at time 1 commonObject.myLong = Long.MAX_VALUE; // In thread 2 at time 2 if(commonObject.myLong > Integer.MAX_VALUE) {
Broken objects The ordering of access to a reference and a constructed object is not guaranteed
If one thread can see an object another thread constructs it might see broken objects (ref available before object constructed)
Double locking // Broken multithreaded version // "Double-Checked Locking" idiom class Foo {  private Helper helper = null; public Helper getHelper() { if (helper == null)  synchronized(this) { if (helper == null)  helper = new Helper(); }  return helper; } // other functions and members... }
Volitile behaviour up until Java 1.4 The Java memory model did not guarantee non reordering on Volatile before 1.5 class VolatileExample { int x = 0; volatile boolean v = false; public void writer() { // Before 1.5 could be done in any order x = 42; v = true; } public void reader() { if (v == true) { //uses x - guaranteed to see 42. } } } // Works with acquire/release semantics for volatile // Broken under current semantics for volatile class Foo { private volatile Helper helper = null; public Helper getHelper() { if (helper == null) { synchronized(this) { if (helper == null) helper = new Helper(); } } return helper; } } Broken up until 1.5 The order of x and v not guaranteed in 1.4
Sending asynchronous messages is complex public void fetchAsync() { Thread t = new Thread(new Runnable() { public void run() {   // Do work in other thread   dataArived("hello"); }   }); t.start(); } public synchronized void dataArived(String s) { // Update data, must be synchronized somehow to be visable }
Reading and writing common data always requires synchronization Sets a limit to scalability
Amdahl's law (simlified):  1/(1 – p)
where P is percentage parallelizable work gives the maximum number of CPU:s that are meaningfull to use when speed is considered.
For example, of 5 percent of the application is serialized because of a common synchronization (such as read on a cache), the maximum number of CPU:s are 20
To fully gain througout by 64 cores about 99 % must be parallelizable
Polopoly on multi core machines
Better data structures from JDK 1.5 – using modern memory management techniques ConcurrentHashMap

More Related Content

Threads and concurrency in Java 1.5

  • 1.  
  • 2. Notes on Concurrent, parallel programming with threads Concurrent = work done in several computational processes, only requires one CPU Parallel = work (computations) done simultaneous, requires multiple CPU:s – locally or distributed
  • 3. GC and Threads and Java CG made easy in Java Person p = null; Concurrent programming made possible (but not easy) Low level support: threads and mutexes volatile boolean stop = false; public void stop() { stop = true; } public void run() { while(!stop) { try { // Do some work Thread.sleep(10); // check stop }catch(InterruptedException ie) { // Ignore } } } // stop = true; thread.interrupt();
  • 4. Some Hard stuff Data visibility between threads Volitile semantics Asynchronous code Race conditions and Deadlocks Congestion/Performance
  • 5. Data visibility Data not guaranteed to be visable between threads without synchronization long and double not even guaranteed to be ”complete” // In thread 1 at time 1 commonObject.myLong = Long.MAX_VALUE; // In thread 2 at time 2 if(commonObject.myLong > Integer.MAX_VALUE) {
  • 6. Broken objects The ordering of access to a reference and a constructed object is not guaranteed
  • 7. If one thread can see an object another thread constructs it might see broken objects (ref available before object constructed)
  • 8. Double locking // Broken multithreaded version // "Double-Checked Locking" idiom class Foo { private Helper helper = null; public Helper getHelper() { if (helper == null) synchronized(this) { if (helper == null) helper = new Helper(); } return helper; } // other functions and members... }
  • 9. Volitile behaviour up until Java 1.4 The Java memory model did not guarantee non reordering on Volatile before 1.5 class VolatileExample { int x = 0; volatile boolean v = false; public void writer() { // Before 1.5 could be done in any order x = 42; v = true; } public void reader() { if (v == true) { //uses x - guaranteed to see 42. } } } // Works with acquire/release semantics for volatile // Broken under current semantics for volatile class Foo { private volatile Helper helper = null; public Helper getHelper() { if (helper == null) { synchronized(this) { if (helper == null) helper = new Helper(); } } return helper; } } Broken up until 1.5 The order of x and v not guaranteed in 1.4
  • 10. Sending asynchronous messages is complex public void fetchAsync() { Thread t = new Thread(new Runnable() { public void run() { // Do work in other thread dataArived("hello"); } }); t.start(); } public synchronized void dataArived(String s) { // Update data, must be synchronized somehow to be visable }
  • 11. Reading and writing common data always requires synchronization Sets a limit to scalability
  • 13. where P is percentage parallelizable work gives the maximum number of CPU:s that are meaningfull to use when speed is considered.
  • 14. For example, of 5 percent of the application is serialized because of a common synchronization (such as read on a cache), the maximum number of CPU:s are 20
  • 15. To fully gain througout by 64 cores about 99 % must be parallelizable
  • 16. Polopoly on multi core machines
  • 17. Better data structures from JDK 1.5 – using modern memory management techniques ConcurrentHashMap
  • 19. Optimized for reads: does not block reads even when its updated
  • 20. Does often not block on updates either
  • 22. Atomic check and take action methods V putIfAbsent(K key, V value); boolean remove(Object key, Object value); V replace(K key, V value); boolean replace(K key, V oldValue, V newValue);
  • 25. May track submitted task and get result back
  • 26. Uses Future and Callable Callable<String> worker = new Callable<String>() { int c = 0; public String call() { try {Thread.sleep(2000L);}catch(Exception ignore){} return &quot;jobb no &quot; + c++; } }; ExecutorService exe = Executors.newSingleThreadExecutor(); Future<String> result = exe.submit(worker); while(!result.isDone()) { // Do something other } String s = result.get();
  • 28. volatile but with conditional atomicity
  • 29. Finer granularity of locking (hardware based)
  • 31. Built on optimistic assumptions: do it, check and redo
  • 32. Non blocking counting AtomicLong at = new AtomicLong(); // one thread, no synchronzied long current = at.get(); // another thread increment, no sync at.incrementAndGet();
  • 33. To really solve the parallelity problem you have to look at the world differently Value (immutable)
  • 34. Identity (holder of values over time)
  • 35. State (value of an identity at a point of time)
  • 37. PDS
  • 38. Clojure Clojure Transaction re-ref (coordinated) Asynchronous Atomic and independent
  • 39. Some buzwords to remember Transactional Memory