--- title: Java Programming 2 - Concurrent Programming tags: java, concurrency, multithreading --- # Java Concurrency ### Concurrency basic * Process vs. thread? * A process has a complete, private set of basic run-time resources; in particular, **each process has its own memory space**. * Threads exist within a process: every process has at least one. * A thread of execution is the **smallest** sequence of programmed instructions that can be managed independently by a scheduler. * **Multiple threads can exist within one process**, executing concurrently and sharing resources such as memory, while different processes do not share these resources. ![](https://i4mk.files.wordpress.com/2013/03/processes-vs-threads.jpg) * Why? * IO-bound tasks: * sockets * blocking read/write * CPU-bound tasks * Monte Carlo simulation? * scheduling/batching * asynchronous tasks * daemons/services * **Parallel** programming? **Concurrent** programming? * You can see the difference in the figure below: ![](https://i.stack.imgur.com/ZktFr.png) * Note that concurrency is possible even on simple systems, without multiple processors or execution cores. * Since JDK5, the Java platform has also included high-level concurrency APIs: **java.util.concurrent** * Java threads can be created as follows. ```java= import java.util.concurrent.Thread; import java.util.concurrent.Runnable; public class ThreadDemo { public static void main(String[] args) { Worker worker1 = new Worker(); worker1.start(); Runnable job = () -> { for (int i = 1; i <= 1000; i++) { System.out.println(i); try { Thread.sleep(1000); } catch(InterruptedException e) {} } }; Thread worker2 = new Thread(); worker2.start(); // do not invoke run() but start() } } class Worker extends Thread { @Override public void run() { for (int i = 1; i <= 1000; i++) { System.out.println(i); try { Thread.sleep(1000); } catch(InterruptedException e) {} } } } ``` ### Difficulty of concurrency * Safety problem: race condition * Memory consistency errors: when two or more threads have access to the same object, especially mutating the attributes. * Key concept: **happens-before relationship**, a guarantee that memory writes by one specific statement are visible to another specific statement. * Solution: **synchronized** methods and synchronized statements * Synchronization is built around an internal entity known as the **monitor lock**. * Every object has an intrinsic lock associated with it. * This monitor lock enforces exclusive access to an object's state and establishes happens-before relationships that are essential to visibility. * **acquire** & **release** * However, this leads to another problem (as listed in the second item). * **reentrant synchronization** ==???== * Atomic access: an atomic action cannot stop in the middle: it either happens completely, or it doesn't happen at all. * Reads and writes are atomic for reference variables and for most primitive variables (all types **except long and double**). ==why?== * Reads and writes are atomic for all variables declared **volatile** (including long and double variables). * Note that you still need synchronized statements/methods for memory consistency. * ```java= import java.util.concurrent.Thread; import java.util.concurrent.Runnable; public class ThreadDemo { public static void main(String[] args) { // example } } ``` * Liveness problem: **deadlock**, **starvation** and **livelock * Deadlock: a situation where two or more threads are blocked forever, waiting for each other. (白話文就是雙方都在等對方。) * [Dining philosophers problem](https://en.wikipedia.org/wiki/Dining_philosophers_problem) ![](https://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/An_illustration_of_the_dining_philosophers_problem.png/330px-An_illustration_of_the_dining_philosophers_problem.png)<- * Sufficient conditions (see [deadlock](http://www.inf.ed.ac.uk/teaching/courses/os/slides/08-deadlock.pdf) or 恐龍書 ): * Mutual exclusion * Hold and wait * No preemption * Circular wait * Starvation: a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. * Livelock: may occur if the other thread's action is also a response to the action of another thread. * Guarded blocks: producer-consumer problem * High-level concurrency objects * Locks * **ReentrantReadWriteLock** * Executors * Executor * execute() * ExecutorService and ScheduledExecutorService * asynchronous * Like execute(), submit() accepts Runnable objects, but also accepts **Callable** objects, which allow the task to return a value. * submit() returns a **Future** object, which is used to retrieve the Callable return value and to manage the status of both Callable and Runnable tasks. * **Thread pools** consist of worker threads because using worker threads minimizes the overhead due to thread creation. * Factory methods: newFixedThreadPool(), newCachedThreadPool(), newSingleThreadExecutor() * Also see java.util.concurrent.ThreadPoolExecutor or java.util.concurrent.ScheduledThreadPoolExecutor. * Fork/Join framework * **ForkJoinPool** * **ForkJoinTask** * Concurrent collections: Thread-safe * **BlockingQueue** * **CopyOnWriteArraySet** * **CopyOnWriteArrayList** * **ConcurrentHashMap** * **ConcurrentNavigableMap** * Synchronizers * **Semaphore** * **CountDownLatch** * **CyclicBarrier** * **Phaser** * Atomic variables * For example, **AtomicInteger**, **AtomicCounter** * check: get, set, compareAndSet, incrementAndGet, decrementAndGet ```java= int count = Runtime.getRuntime().availableProcessors(); ```