Concurrency and Multi-threading
# Process and Threads
- A
processis an instance of a program or an application- The operating system loads an application inside a process
- The OS can execute many processes at the same time
- Process contains an image of application code
- It has some memory and other resources
- The operating system loads an application inside a process
- A
threadis a sequence of instructions within a process (A thread of instructions)- Each process has at least one thread called the
main thread - More processes can be created to run tasks concurrently
- e.g. build a web server that can serve many clients at the same time
- Serve each client using a separate thread (
Multiple Treading) - Multi-threaded Application
- Multi-core computers can run many processes or threads
- Serve each client using a separate thread (
- Each process has at least one thread called the
public class Main {
public static void main(String[] args) {
System.out.println(Thread.activeCount());
// 2: 1 is the main thread, the other is the background thread that runs the garbage collector
// garbage collector removes unused objects from memory
System.out.println(Runtime.getRuntime().availableProcessors());
// 8 (we have 8 available but we just used 2 of them; the number depends on your machine)
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# Starting a Thread
public class ThreadDemo {
public static void show() {
// current thread name is different from the download thread
System.out.println(Thread.currentThread().getName());
for (var i = 0; i < 10; i++) {
Thread thread = new Thread(new DownloadFileTask());
therad.start(); // these threads have different names; they run in parallel
}
}
}
public class DownloadFileTask implements Runnable {
@Override
public void run() {
System.out.println("Downloading a file: "+Thread.currentThread().getName());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Pausing a Thread
public class DownloadFileTask implements Runnable {
@Override
public void run() {
// We can put a thread to sleep, so it takes 50 seconds to finish 10 download
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
- Thread scheduling: if have more tasks then threads, scheduler will switch among tasks, giving each a slice of CPU time, giving one the illusion that they are run in parallel
# Joining a Thread
public class ThreadDemo {
public static void show() {
Thread thread = new Thread(new DownloadFileTask());
therad.start();
// let the main thread to wait for the completion
// block current main thread from doing any other things
try {
Thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# Interrupting a Thread
public class ThreadDemo {
public static void show() {
Thread thread = new Thread(new DownloadFileTask());
therad.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt(); // does not force thread to stop
// it sends an interrupt request
// thread needs to handle that request
}
}
public class DownloadFileTask implements Runnable {
@Override
public void run() {
for (var i = 0; i < 10_000; i++)
// handle interruption
if (Thread.currentThread().isInterrupted()) return;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Concurrency Issues
Race Condition: multiple threads are competing to modify some dataVisibility Problem: different threads have different views of the shared data as changes are not visible to other threads- Therefore, we need
Thread-safe Code
# Race Conditions
package com.codewithmosh.concurrency;
import java.util.concurrent.atomic.LongAdder;
public class DownloadStatus {
private int totalFiles;
public int getTotalBytes() {
return totalBytes.intValue();
}
public void incrementTotalBytes() {
totalBytes.increment();
}
}
public class ThreadDemo {
public static void show() {
var status = new DownloadStatus();
List<Thread> threads = new ArrayList<>();
for(var i = 0; i < 10; i++) {
Thread thread = new Thread(new DownloadFileTask(status));
thread.start();
threads.add(thread);
}
// wait for all download threads to finish
for(var thread : threads) {
try {
Thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class DownloadFileTask implements Runnable {
@Override
public void run() {
for (var i = 0; i < 10_000; i++) {
if (Thread.currentThread().isInterrupted()) return;
status.incrementTotalBytes();
// race condition, the total bytes will be different each time we run
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# Strategies for Thread Safety
Confinement: not to share data across threads in the first place- confine or restrict each thread to have its own data
Immutability: use immutable or unchangeable objects- An object is
immutableif its data cannot be changed after creation - These are read-only objects
- An object is
Synchronization: Prevent multiple threads from accessing the same object concurrently- Synchronize or coordinate the access to an object across different threads by using locks
- Only one thread at a time can change that part
- It is against the idea of concurrency
- Implementing synchronization is challenging error-prone
- Deadlock: two threads wait for each other indefinitely
- This is bad, avoid it as much as possible
Atomic Objects: these classes allow us to achieve thread-safety without using locks- They are like atoms, they cannot be broken down
Partitioning: partition data into segments that can be accessed concurrently- Multiple threads can access a collection of object, but only one thread at a time can access a segment in that collection
# Confinement
# Locks
# The Synchronized Keyword
# The Volatile Keyword
# Thread Signaling with wait and notify
# Atomic Objects
# Adders
# Synchronized Collections
# Concurrent Collections
上次更新: 2022/12/04, 16:55:22