CS202 Review Session 3 Notes from [Xiangyu Gao](https://xiangyug.github.io/), TA from fall 2021 Edited by Khanh Nguyen, TA Spring 2022 Edited by Jinli Xiao, TA Spring 2023 Edited by Sophia Watts, TA Spring 2024 1. Process and thread 2. What is concurrency? 3. Concurrency Commandment 4. C++ primer 5. Lab 3 overview 5.1 Producer-Consumer architecture 5.2 Lab 3 architecture 5.3 Notable files 5.4 Common pitfalls 6. Sequential Consistency 7. Q&A 8. Resources --------------------------------------------------------------------- 1. Process and thread Process: - an instance of a program. - each process has its own memory space and system resources (like file handles and network connections). - processes are isolated, so the crash of one process won't affect others. Thread: - a unit of execution within a process. - a single process can be referred to as a single-threaded process. A process can have many threads, referred to as multi-thread. - different threads in a process share address spaces and resources. - if a thread crashes, it can cause the entire process to crash. 2. What is concurrency? - "It's when there are multiple threads?" - "It's when things execute at the same time" It's true. That's what concurrency is: multiple things happening at the same time, competing for shared resources. Multi-threading, mult-processing, and asynchronous programming are all forms of concurrency. Why concurrency? Allows for one process to work on I/O and computation at once, more efficient In a concurrent system, multiple tasks can be executed at the same time. For example, a computer system can run Zoom, Spotify, and a game simultaneously. However, programs sometimes need to share resources. For example, multiple threads may need to read or write the same file. This can easily cause problems if they access the file concurrently, resulting in one thread reading inconsistent data from the file. In the programming world, various concurrency models and primitives have been developed to control access to shared resources. These include monitors, message passing, mutexes, conditional variables, and semaphores. In CS202, we will be using a monitor, which is a combination of mutexes and conditional variables, to handle concurrency. 3. Concurrency Commandment - Rule 1: always acquire/release locks at beginning/end of methods - Rule 2: always hold lock when doing condition variable operations - Rule 3: a thread in wait() must be prepared to be restarted at any time, not just when another thread calls signal - Cannot replace broadcast() with signal(). But can replace signal() with broadcast() in cases where we don't care about extra wake-ups. 4. C++ primer a. Destructor: - Syntax: classname::~classname(). E.g: TaskQueue::~TaskQueue() - Opposite of constructor - Used to clean up memory, destroy mutex and conditional variables b. Freeing dynamically allocated memory - Syntax in C++ is delete. E.g: delete POINTER_GO_HERE c. Printing - printf(...) - std::cout << ""... 5. Lab 3 overview 5.1 Producer-Consumer architecture [See recording] 5.2 Lab 3 architecture [See recording] Coarse-grained lock: - The whole store/object shares one lock and conditional variable Fine-grained lock: - Each item in the store has its own lock 5.3 Notable files - sthread.cpp: our thin wrapper around pthread. Use this as your threading library - TaskQueue.cpp: the task queue that suppliers and consumers dequeue to operate on - estoresim.cpp: main entry point for the code, creating threads - EStore.cpp: the shared object that suppliers and consumers are operating on - RequestHandlers.cpp: handler so that worker thread knows what to do 5.4 Common pitfalls: - Forgot to use destructor to free/destroy resources - Forgot to release the mutex - Has code of the form: int condition = some_condition while(condition) { .... } -> This is wrong because condition might rely on shared variables so need to be recomputed 6. Sequential Consistency - "Informally, sequential consistency implies that operations appear to take place in some total order, and that that order is consistent with the order of operations on each individual process” (https://jepsen.io/consistency/models/sequential) Mental Model: T1: ---------A1------------A2------ T2: ------B1-------------B2------- In sequential consistency model, we can think of this as a game where you have to provide an ordering of all the events across all the threads. But the catch is that you can't re-order event within single thread. However, order across different thread can be re-ordered For instance, here are some valid order: - B1-A1-A2-B2 - B1-A1-B2-A2 - A1-B1-A2-B2 And here is some invalid order: - B1-A2-A1-B2 // A2 happens before A1 but both in T1 - B2-B1-A1-A2 // B2 happens before B1 but both in T2 7. Q&A 8. Resources: - JS Event Loop visualizer: https://www.jsv9000.app/ - Jepsen: https://jepsen.io/consistency/models/sequential