9 Threading
This chapter is devoted to threads, locks and
condition variables.
9.1 The Program
The following program creates twice as many output threads as there are cores in the machine.
Each output thread generates ten times a hello message in its main function OutputThreadMain().
The program has also an output collector class whose Run() method is also run in a thread.
The output threads insert their output lines to the end of the collector's outputLines list
by calling the output collector's WriteLine() method.
The collector's outputLines member variable is an ordinary List<string>,
that is not synchronized by default. Therefore we need a lock object, outputLock, that
synchronizes access to the outputLines list by using lock statements.
After an output thread has added its message to the end of the outputLines list it also notifies a
condition variable outputAvailableOrExiting, that wakes up the output collector.
The output collector removes messages from the head of the outputLines list, prints them to the console,
and goes back to sleep waiting for more lines to output or exiting variable to become true.
It may happen that many output threads manage to insert their output to the output lines before the collector wakes up,
so that there may be more output lines than collector wake ups, so the collector empties the list each time it wakes up.
The main function of the program consists of starting the output collector thread and the output threads,
then waiting that the output threads end, and finally signaling the exiting condition to the collector and
waiting that the collector thread ends.
9.2 Output
Here's the output of the program when run on my machine, that has four cores:
> cminor run assembly/debug/threads.cminora
1: hello 0 from thread 1
2: hello 0 from thread 0
3: hello 0 from thread 2
4: hello 0 from thread 5
5: hello 0 from thread 3
6: hello 0 from thread 4
7: hello 1 from thread 1
8: hello 1 from thread 2
9: hello 1 from thread 4
10: hello 1 from thread 3
11: hello 1 from thread 5
12: hello 2 from thread 3
13: hello 2 from thread 4
14: hello 2 from thread 2
15: hello 2 from thread 5
16: hello 3 from thread 3
17: hello 3 from thread 5
18: hello 3 from thread 2
19: hello 2 from thread 1
20: hello 4 from thread 5
21: hello 3 from thread 4
22: hello 1 from thread 0
23: hello 4 from thread 3
24: hello 5 from thread 5
25: hello 4 from thread 4
26: hello 2 from thread 0
27: hello 5 from thread 4
28: hello 4 from thread 2
29: hello 3 from thread 0
30: hello 0 from thread 6
31: hello 5 from thread 3
32: hello 3 from thread 1
33: hello 6 from thread 4
34: hello 1 from thread 6
35: hello 6 from thread 3
36: hello 4 from thread 1
37: hello 6 from thread 5
38: hello 7 from thread 4
39: hello 4 from thread 0
40: hello 5 from thread 1
41: hello 0 from thread 7
42: hello 5 from thread 2
43: hello 2 from thread 6
44: hello 8 from thread 4
45: hello 1 from thread 7
46: hello 7 from thread 5
47: hello 3 from thread 6
48: hello 2 from thread 7
49: hello 6 from thread 2
50: hello 9 from thread 4
51: hello 8 from thread 5
52: hello 6 from thread 1
53: hello 3 from thread 7
54: hello 4 from thread 6
55: hello 7 from thread 1
56: hello 9 from thread 5
57: hello 7 from thread 3
58: hello 7 from thread 2
59: hello 4 from thread 7
60: hello 8 from thread 1
61: hello 8 from thread 2
62: hello 8 from thread 3
63: hello 5 from thread 7
64: hello 9 from thread 1
65: hello 9 from thread 3
66: hello 5 from thread 0
67: hello 6 from thread 7
68: hello 9 from thread 2
69: hello 5 from thread 6
70: hello 6 from thread 6
71: hello 7 from thread 7
72: hello 6 from thread 0
73: hello 7 from thread 0
74: hello 8 from thread 7
75: hello 7 from thread 6
76: hello 8 from thread 0
77: hello 8 from thread 6
78: hello 9 from thread 7
79: hello 9 from thread 0
80: hello 9 from thread 6