CS202 Review Session 4 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 Edited by Saeed Bafarat, TA Fall 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. Process Visualization: ---------------- | Stack Thread 1 | ---------------- | | | Stack Thread 2 | ---------------- | | | Heap | ---------------- | | | Program Code | ---------------- The entire thing is one process, but has one or more threads each with their own stack. However, they share one heap hence we have concurrency. Note: the stacks above have an invalid page between them which stops them from clobbering each other. 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, multi-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. Why C++: Allows us to create and use classes. 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 instead of free c. Printing - printf(...) - std::cout << ""... d. In case want to use C printf(...) do #include and just use the C String you are used to. 5. Lab 3 overview 5.1 Producer-Consumer architecture - Creating a store where producers can add items or change their attributes while consumers buy it if they have the budget - Why this lab: to give students practice in using threads and monitors 5.2 Lab 3 architecture 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 (to avoid do grep -i smutex_init and check that it has a corresponding smutex_destroy) - Forgot to release the mutex (to avoid do grep -i smutex_lock and check that it has a corresponding smutex_unlock) - 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 Example: Want to buy an item but you do not have the budget If you do price=item.id then do while(budget