---
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.

* 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:

* 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)
<-
* 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();
```