CSE 381 Exam 2
how to create a symlink (or symbolic/soft link)
$ ln -s zero_link2.dat zero_symlink.dat
how to create a link (or hard link)
$ ln zero.dat zero_link1.dat
illustrate a command that can be used to verify if a file named hello.cpp exists in the present working directory.
$ ls hello.cpp
creating and managing multiple threads
- 2 loops are needed: one to create the threads and one to join the threads - the slowest thread determines the runtime of the second/join loop
process v threads
- a process does not share resources with other processes, a thread shares resources - processes can be terminated independently of other processes, killing one thread kills all other threads and the entire process -process uses heavyweight context switching, thread uses light weight context switching -processes have special streams for i/o, threads share the parent process's streams -processes allow for redirection or piping i/o, threads cannot use redirection or piping and instead use shared data
how fo most modern CPUs support synchronization at the hardware level?
- can use special CPU instructions that are much faster than software solutions - can only be used on types directly supported by the CPU (primitive types)
std::thread
- class in C++ that runs threads -threads start running a given method - thread method can call other methods - a thread stops running when their thread method ends
Using multiple mutexes
- each shared resource should be controlled by its own mutex (ONE THREAD CAN USE ONE MUTEX AT A TIME) - reduces the thread-contention for a mutex - maximizes opportunity for threads to operate independently 1. thread locks the appropriate mutex prior to using the resource 2. thread uses the resources 3. thread unlocks the mutex
one to one threads
- each thread is represented by a separate LWP -kernel is explicitly managing each thread -common model
one to many/ reduction data parallel MT
- each thread operates on one or more input-output pair - each thread has an independent subset of data -each thread generates its local, indeterminate result -main thread computes overall result -used for sum, median, find, maximum, mode, etc.
one to one data parallel MT
- each thread operates on one or more input-output pairs - each thread has an independent subset of data -for each input, one output is generated
task parallel MT
- each thread runs different algorithms -input data is the same for each thread - works well for a small number of files
Data Parallel MT
- each thread runs the same algorithm - input data is different for each thread - each thread must update independent memory locations (sharing read-only/const data between threads is not an issue)
core
- essentially a sub-CPU that can independently process instructions -typically instructions on a program are processed using one thread running on one core
disadvantages of multithreading
- have to correctly subdivide the problem between threads - need to correctly coordinate or synchronize the threads
What operations on an atomic object are MT safe?
- increment, decrement, and assignment operations
What happens when a thread is killed?
- kills the entire process and all threads in the process (INCLUDING MAIN THREAD)
std::lock_guard
- locks a given mutex in the constructor -automatically unlocks the mutex in the destructor -prevents deadlock -exception proof - the critical section spans the scope of the lock_guard object
one to many threads
- multiple threads map to a single LWP/kernel thread - LWP decides on the user-thread (or method) to be run
deadlock
- occurs when a mutex is not unlocked, all threads are blocked from entering a critical section - common multithreading problem - can be avoided using std::lock_guard -program hangs
Priority Inversion
- occurs when threads of different priority try to lock the same lock -lower-priority process holds a lock needed by a higher-priority process - OS keeps scheduling the high priority thread and does not schedule the low priority thread, low priority is unable to give up the lock to the high priority thread, degrades performance - std::lock method uses dining philosophers approach so we will not deadlock
multi threaded web server
- process each request using a separate thread - accepts connections from multiple clients - run faster than single threaded web servers
single threaded web server
- process runs 1 request at a time, using 1 thread - accepts connections from multiple clients
How many mutexes should we have in a multithreaded program?
- synchronization slows threads so we should have a SEPARATE mutex for each shared variable
Data-Parallel/Synchronization free MT programs
- threads do not update (or write) shared memory -each thread operates using its own memory locations -synchronization is not needed
monitors/condition variables
- used in sleep wakeup producer consumer model - need a mutex to operate - c++ has std::condition variable object -std::condition needs a std::unique_lock to operate -notifies other waiting threads about potential change in wait status -enables blocking and yielding until condition is met - avoids busy waiting
sleep wake approach
- uses conditional variables - involved, but more efficient -eliminates busy waiting - modern OS provide support for sleep-wake up approaches through monitors/condition variables
busy wait approach
- uses standard mutexes and locks - simpler but consumes CPU time (wastes CPU cycles) -producer consumer threads use 2 CPU cores even when no effective work is done - GOOD FOR INTERACTIVE TASKS (video games, etc.) AND INTERACTIVE SYSTEMS (self-driving cars, etc.)
PS (Linux Command)
-Can view the current processes • And the process ID (PID) • Similar to the Windows Task Manager -View current user processes • "ps" command -View all processes • "ps -e | more" command
sanitizers
-GNU library provides sanitizers to check for race conditions, the program must be compiled with thread sanitizers
PID of threads
-PID is the same for all threads in a process
rm (Linux Command)
-Remove files or directories • Deletes the files -Does not remove directories by default • Directories must be empty to be removed or must be removed with -r option
vi (Linux Command)
-Visual mode editor • Full screen editing with copy, paste, and more -vi FILE • "> vi script.sh" starts the editor for the file script.sh -To insert text • Enter "i" and then <text> • Exit insert mode with Esc -Save (write) the file and quit vi • ":wq" command
file system
-a standard or convention used to store information on permanent storage -A method used by operating systems to store, retrieve, and organize files. -"data structure" on disk or storage devices, PHYSICAL STORAGE IS ORGANIZED INTO A SERIES OF BLOCKS
What is a binary semaphore
-aka a mutex -used to create a critical section in the following manner -- Threads try to lock the mutex via a system call to let other threads know they have to block. If they are unsuccessful the OS waits until the mutex is zero (i.e., no other thread is using it).
Namespace
-allows for encapsulation - does not pollute the global scope, can be used instead of global variables namespace name { }
multithreaded program properties
-allows multiple commands, or threads to run simultaneously -can have two or more threads -threads share program, memory, and file descriptors -Stack is not shared
detaching a thread (background threads)
-allows the thread to run asynchronously -the main thread does not have to wait for detached threads to finish -slower requests so not hinder other requesrs
std::condition wait() method
-allows us to wait until a thread is woken up to acquire the lock -an optional predicate (method that returns a boolean value) is satisfied(i.e. lambda returns true)
lambdas(first-class functions)
-anonymous methods -designed to improve functionality and code readability -usually very short - can be arguments to another method/function, can be returned by a method, can be stored as a variable
percent cpu
-average number of cores utilized by the program -each core is counted as 100% (ex: 3 cores would be 300%) - on lightly loaded machines this value is a rough estimate of the number of concurrent threads running in a process
solution to avoid race conditions
-avoid concurrent updates to shared resources -at any given time only one thread is allowed to modify a shared value - before and after the critical sections multiple threads are operating concurrently
std::mutex
-class that manages the critical section - should be shared by all threads - threads lock and unlock the mutex, the OS only allows one thread to acquire the lock
std::atomic<>
-class that provides atomic MT safe primitive types - after their definition they can be used as any other regular variable -operations on them are thread safe so a race condition cannot occur - can be used in containers like vectors, maps, etc.
producer consumer model
-exchange of data between threads of varying speeds is accomplished using intermediate, finite-size queues or buffers -used in online transaction processing -aims to balance the overall system throughput and performance
critical section
-for updating shared resources - ONLY ONE THREAD CAN OPERATE AT A TIME - created using mutex and locks - scope is very important in critical sections -should be brief and not contain i/o
producer threads
-generate data and add it to the queue if there is available space -only wait when the queue is full
data parallel MT applications
-image processing -file processing
multithreading
-instructions or tasks in a program are logically organized into independent subsets and processed by multiple threads -helps reduce relative runtime constants
Light weight process (LWP)
-name for threads in Linux -can be observed using $ps -aL command
std::future
-object returned by a std::async thread -eases obtaining the return value of a method -future's get method blocks until the thread joins when it is called and returns the value from the method f
passing by reference with threads
-pass by reference works differently with threads because threads have their own stacks created by the OS when a thread is started - std::ref() must be used for refrences, std::cref() for constant references otherwise the program will not compile
consumer threads
-process next available data from the queue -only wait until queue is empty
semaphores
-special counter managed by the OS -Operations on the semaphore are guaranteed to be thread-safe by the OS -a condition that specifies that only one process may update (modify) a shared resource at a time to ensure correct operation and results
locking two mutexes with std::lock
-std::lock(mutex1, mutex2); -locks two mutexes simultaneously while avoiding deadlocks - uses dining philosophers approach so we will not deadlock - will NOT automatically unlock the two locked mutexes
std::async
-streamlines task parallel programming - runs a given method f in a separate thread, returns quickly after starting the thread -returns a std::future object -does not guarantee threads will be created
what happens when a lock condition is not met?
-the thread releases the lock and goes to sleep, another thread has to wake up this thread -when the thread wakes up it reacquires lock
MT programs that require snchronization
-threads that need to update(or write) to shared memory -need to ensure to coordinate or synchronize threads to prevent race conditions
user time
-total CPU time for running instructions in the user's code - the time it would take if the program was run using 1 core - Sum of time for all threads for which program was running on the CPU.
thread
-unit of execution managed by OS -sub-processes or light weight processes
Race Condition
-unsynchronized updates to shared variables causes incorrect program behaviors -causes indeterminate results
.h vs .cpp files
.h usually contains just prototypes and implementation for 1-liner methods, .cpp contains implementation for methods
Assume the timing (and other runtime characteristics) of a program called ./magic has to be measured, with command-line arguments 5 "test" ~/. The correct bash shell command is:
/usr/bin/time ./magic 5 "test" ~/
Assume that the following unordered_map is to be operated upon by multiple threads from in the threadMain method. namespace mt { const std::unordered_map<int, std::string> vals = {{1, "one"}, {2, "two"}, {3, "three"},}; } void threadMain(int id) { auto curr = mt::vals.at(id % 3); // Rest of code not shown for brevity mt::vals.at(id % 3) == curr; } The number of mutex that should be used to maximize concurrency would be:
0
Assume that the following vector is to be operated upon by multiple threads from in the threadMain method. namespace mt { std::vector<int> vals(5); // list of 5 zeros. } void threadMain(int id) { // Rest of code not shown for brevity mt::vals.insert(vals.begin(), id); mt::vals.pop_back(); } The number of mutex that should be used to maximize concurrency would be:
1
Given n inputs and k threads, the overall final output from a reduction type multithreaded program is
1
The minimum number of threads that are present in a standard process created by modern operating systems would be:
1
The number of concurrent threads created by the following code fragment is: std::vector<std::thread> threads; for (int i = 0; (i < 10); i++) { std::thread t(doIt, i); t.join(); } for (auto& t : threads) { t.join(); }
1
Assume that the following unordered_map is to be operated upon by multiple threads from in the threadMain method. namespace mt { std::unordered_map<int, std::string> vals = {{1, "one"}, {2, "two"}, {3, "three"},}; } void threadMain(int id) { auto curr = mt::vals[id]; // Rest of code not shown for brevity mt::vals[id] = curr; } The number of mutex that should be used to maximize concurrency would be:
1 (Operator[] can add an entry if the key does not exist. So only 1 thread can ever use operator[]. So we need only 1 mutex.)
The minimum number of CPUs/core that is required to create a race condition is:
1 CPU with 1 Core
On modern computers, the time to create a thread is typically
1 millisecond
Study the following program: int slow(int i = 2) { sleep(1); // sleep for 1 second return i; } int main() { int result = 0; auto launch = std::launch::async; auto fut1 = std::async(launch, slow, 1); auto fut2 = std::async(launch, slow, 2); result += fut1.get(); result += fut2.get(); std::cout << result << std::endl; } Given the above code, the runtime of the above program will approximately be
1 second
two categories of synchronization free MT programs
1. Data Parallel 2. Task Parallel
Thread implementations in OS
1. One to one 2. One to many
three steps of changing a variables value
1. Read value of a variable from memory into CPU register 2. use ALO to perform operation using CPU register 3. write the value in the CPU register back to memory
two producer consumer implementations
1. busy-wait approach 2. sleep-wakeup approach
pros of having different threads do different operations
1. each thread is simpler to develop 2. operate using the same subset of resource, lock management is streamlined 3. better load-balance and use of multi-core CPUs
file system blocks purpose
1. ease user operations 2. enable efficient use of storage 3. provide fault tolerance
types of links
1. links (aka hard links) 2. soft links/ symbolic links/ symlinks (if source file is deleted this link breaks)
two loop pattern for data parallel async multithreading
1. loop to call async to first create threads and get futures 2. separate loop to call get on futures (that calls join on threads)
functionalities of a file system
1. manage access permissions for files 2. allow linking (or cross-references) to files
four rules to avoid race conditions
1. no two threads can be in a critical section simultaneously ( a program can have several separate critical sections) 2. no assumptions can be made about the speed or number of cores/CPUs 3. no thread outside a critical section can block a thread inside the critical section 4. no thread should wait too long (over 1 millisecond) to enter the critical section
Sharing objects between threads
1. one object per thread 2. one object shared by all threads
dining philosophers synchronization problem
1. two locks are needed by each thread simultaneously 2. when a mutex cannot be locked immediately, a thread should release locks and try again(otherwise this will cause a deadlock) Solution: we can lock both locks simultaneously using std::lock(mutex1, mutex2);
Given the following code fragment, the number of times the string object str is created-and-destroyed in the doIt method is: void doIt() { for (int i = 0; (i < 10); i++) { std::string str; // Rest of the code not shown for brevity } }
10
Study the following program: int slow(int i = 2) { sleep(1); // sleep for 1 second return i; } int main() { int result = 0; auto launch = std::launch::async; auto fut1 = std::async(launch, slow, 1); result += fut1.get(); auto fut2 = std::async(launch, slow, 2); result += fut2.get(); std::cout << result << std::endl; } Given the above code, the approximate runtime of the program will be
2 seconds
A program was run on a very lightly-loaded machine with 8 cores. Given the following output from /usr/bin/time, what was the total time was spent running instructions as part of system calls? 4.17user 2.74system 0:05.10elapsed 374%CPU (0avgtext+0avgdata 22032maxresident)k 117184inputs+0outputs (0major+6143minor)pagefaults 0swaps
2.74 seconds
Assume that the following unordered_map is to be operated upon by multiple threads from in the threadMain method. namespace mt { std::unordered_map<int, std::string> vals = {{1, "one"}, {2, "two"}, {3, "three"},}; } void threadMain(int id) { auto curr = mt::vals.at(id % 3); // Rest of code not shown for brevity mt::vals.at(id % 3) = curr; } The number of mutex that should be used to maximize concurrency would be:
3
The actual number of micro-operations involved in executing a simple x++ (where x is int) is:
3 micro-operations (namely, read → increment → write)
A program was run on a very lightly-loaded machine with 8 cores. Given the following output from /usr/bin/time, how long (as perceived by the user) did the program take to run? 4.17user 2.74system 0:03.10elapsed 374%CPU (0avgtext+0avgdata 22032maxresident)k 117184inputs+0outputs (0major+6143minor)pagefaults 0swaps
3.10 seconds
A program was run on a very lightly-loaded machine with 8 cores. Given the following output from /usr/bin/time, how many threads were run on an average? 4.17user 2.74system 0:03.10elapsed 374%CPU (0avgtext+0avgdata 22032maxresident)k 117184inputs+0outputs (0major+6143minor)pagefaults 0swaps
4
Assume that the maximum available virtual memory to a process is 4 GB. Assume 10 processes, each process with 4 threads (total 40 threads) are running on the server. Assume threads are using equal amounts of memory. The maximum available virtual memory for each process is limited to
4 GB
A program was run on a very lightly-loaded machine with 8 cores. Given the following output from /usr/bin/time, what was the total time was spent running instructions in userspace? 4.17user 2.74system 0:03.10elapsed 374%CPU (0avgtext+0avgdata 22032maxresident)k 117184inputs+0outputs (0major+6143minor)pagefaults 0swaps
4.17 seconds
Assume that the following vector is to be operated upon by multiple threads from in the threadMain method. namespace mt { std::vector<int> vals(5); // list of 5 zeros. } void threadMain(int id) { auto curr = mt::vals.at(id % 5); // Rest of code not shown for brevity mt::vals.at(id % 5) = curr; } The number of mutex that should be used to maximize concurrency would be:
5 (Given n independent resources (being updated/modified) you should prefer to use n separate mutex to maximize concurrency.)
Assume that the following method is called on 5 threads. How many times is the mutex locked/unlocked in the following code? using Guard = std::lock_guard; // This method is called from 5 threads void thrMain(int& x, std::mutex& m) { for (int i = 0; (i < 10); i++) { Guard lock(m); x++; } }
50
How many bytes are in a block?
512 bytes
Assume a server has 2 CPUs, with each CPU having 4 cores. The maximum number of threads that can be "running" (i.e., using CPU resources) in parallel on the server is:
8
LWP ID for main thread
= LWP ID will always be the same as the PID -this is the first thread, runs the main function
What is a Monitor or std::condition_variable? How is it different from a std::unique_lock?
A condition_variable is used to meet 2 cases simultaneously -- (i) block and wait until a specific condition is satisfied and (ii) a lock on a given mutex can be acquired. A std::unique_lock does not operate on a condition but is just used for locking/unlocking a mutex.
What is a std::unique_lock? What is the key difference between a std::unique_lock and a std::lock_guard?
A unique_lock enables repeated locking and unlocking of a mutex by 1 unique thread. However, a lock_guard is a 1-time locking/unlocking operation!
Given the following block allocation table, what is the next block to be read after a given block number?
All you have to do is, given a block number, literally look inside the box with that number.
The LWP ID (aka thread ID) of the main thread is
Always the same as PID
When can pass-by-reference in the thrMain method cause a memory issue?
An issue can be caused if the argument being referenced is a local variable being destroyed at the end of its scope because then threads will have a reference to a non-existing variable and will have catastrophic errors
computer system
An organization of hardware and software designed to accomplish a data processing function.
Which one of the following applications is a good candidate for use with detached threads?
Asynchronously printing a timer value once a second
A std::atomic enables fast mutexes because
Atomics use special CPU instructions
Which resource is not shared between multiple threads:
CPU registers
File permissions
Control what you can do to a file:(Read, Read/Write, Full Control) three chars for user group and others (ex: rw-r--r--)
mkdir (Linux Command)
Creates a directory
Programs that do not require coordination or synchronization between threads are called
Data parallel programs
Given an 8 core CPU, the maximum number of threads that can be created in a single process is limited to:
Depends on the maximum threads supported by the OS
A std::lock_guard unlocks a a given std::mutex in its
Destructor
What is the primary motivation for systems programming?
Develop software such as operating systems, web-servers, etc.
A thread sanitizer is a
Feature of C++ compiler
How to count the number of links (or hard links) from the output of the ls -l command?
For hard links, check the number before the user-id (in this case 'root') to see if it is > 1 and then subtract 1 from the number to see how many links exist.
how to check if there is a link (or hard link) in the output of the ls -l command?
For hard links, check the number before the user-id (in this case 'root') to see if it is > 1.
nice
GNU/Linux command used to change the scheduling priority of threads
The key idea in the first step in a "reduction" type data parallel program is to:
Generate few intermediate results
syscall
Generates a system call exception that transfers control to the processor and allows access to a dedicated location in supervisor code space.
What is an open system, from a software perspective?
Has a user interface
Which of the following resources is shared between multiple threads?
Heap (i.e., dynamic memory)
IP
Internet Protocol
If a std::mutex has methods to lock and unlock it, then what is the purpose of a std::lock_guard?
It is important to always unlock a mutex to avoid deadlocks. The std::lock_guard uses C++ constructor-and-destructor semantics to ensure that the mutex is always unlocked, even if exceptions occur in a code.
The acronym LWP stands for
Light Weight Process
Why does the disk usage not change when we create links (or hard links)?
Links are just inode entries. When the directory was created 1 block on this file systemw as reserved to store initial set of inodes. Since the inodes do not take much space, there is no increase in disk usage as links are created. However, if many links are created, then space for inode entries will increase and the disk usage will increase (in steps of block size)
Futex
Linux syscall used to lock a mutex
The acronym MT-safe stands for multithreading-safe which means that
Method can be called from multiple threads without causing race conditions
examples that are NOT systems:
NIC Data communication network
The most common approach used for supporting threads on modern operating systems is:
One-to-one threads
A critical section is
Part of a multithreaded program where shared value(s) are updated
What is the best/ fastest MT approach?
Synchronization free approaches
How does multithreading improve the performance of a program?
The OS tries to run each thread on an independent CPU-core, assuming sufficient CPU-cores are available (so it is dependent on hardware/ Virtual Machine configuration) In theory, given k cores, the runtime is a program is reduced from t (on 1 core) to t/k
When get() method is called on a std::future object, the get() method:
The call blocks until the future value is set without waiting on thread.
hard link vs soft link inodes
The hard links refer to the same content on disk and same set of blocks. However, symlink refers to a different file entry and requires a different inode to store information about the symlink. In addition, the symlink can have different set of permissions. Consequently, the symlink has a separate inode number to store the information.
What is used to start threads in a program?
The line of code that calls the thread's constructor (std::thread) created the thread
Assume a thread is trying to acquire a lock on a mutex by calling the lock() method? How long does the lock() method take to return?
The lock() method takes an indefinite amount of time (seconds or even hours) to finish. Ideally, if a program is correctly developed, then the lock() method should return in a few milliseconds. However, if a thread is a low priority thread, then lock() method may take seconds or even hours to return. If the program has a bug and is experiencing a deadlock, the lock() method may never return!
Why is there a discrepancy in the number of threads reported by the OS versus the number of threads the program claims to create?
The number of threads reported by the OS is 1 more than the number of threads created by the program. This is because every process has 1 thread that is running the main method, which then starts n more threads resulting in 1+n threads.
What is path to a file?
The path to a file describes its location within the directory structure.
What is the primary motivation for multithreading a given program?
The primary motivation behind multithreading a given program is to reduce the overall runtime of the program by effectively utilizing CPUs or CPU-cores
Assume three threads (all with the same priority) are trying to lock a std::mutex. Which thread will most likely get to lock the mutex? The first one that called lock() or the last one that called lock()?
There is no guarantee which thread will get to lock the mutex. It is up to the OS to manage and arbitrate the locks between these threads. So, we should not make any assumptions on which thread will be the first one to successfully acquire the lock.
TCP
Transmission Control Protocol - provides reliable, ordered, and error-checked delivery of a stream of packets on the internet. TCP is tightly linked with IP and usually seen as TCP/IP in writing.
Would it be possible for multiple threads to operate on independent entries of an unordered map?
True there isn't much difference between vector and map. They both need to be pre-populated with initial entries for the threads to operate on.
chmod command
Used to change permissions on a Linux system
dot ( . ) command
Used to execute the contents of a shell script within the current execution context
HTTP GET request
Used to retrieve resource from server
Battery operated vibration sensors is being designed to be placed at remote locations to record seismic activity. The sensor is being designed for long durations. Its uses producer-consumer based multithreading to combine data from several accelerometers, only when they sense vibrations. A good approach for implementing the producer-consumer model would be:
Using a sleep-wakeup approach (i.e., using condition_variables) Long-duration battery operation requires energy efficiency. In addition, inputs occur only intermittently (on when vibrations occur) so the queues are mostly going to be empty and there is no point in spinning checking these queues and wasting energy.
A video processing web-server (like YouTube) uses multiple threads to process a video (to convert into different quality-formats, closed-captioning, etc.) using producer-consumer approach. A good approach for implementing the producer-consumer model would be:
Using a sleep-wakeup approach (i.e., using condition_variables) Such applications are not interactive systems. Hence, a quick frame-by-frame response is not needed.
A video game uses producer-consumer model to manage a variety of operations performed by multiple users (each user with their own controller) on a gaming console. A good approach for implementing the producer-consumer model would be:
Using busy-wait approach (i.e., using spin-locks)
A self-driving electric (battery life is somewhat important) car uses the producer-consumer multithreading model to process data from multiple sensors for driving the car. A good approach for implementing the producer-consumer model would be:
Using busy-wait approach (i.e., using spin-locks) Self-driving cars have to react quickly to avoid accidents and energy is only a secondary issue when compared to saving lives.
shortcomings of busy waiting
WASTED CPU CYCLES The producer thread spins in the loop, when queue is full The consumer thread spins in a loop, when queue is empty
Given the following code to create shared pointers to TCP streams, the client stream is closed when void runServer(tcp::acceptor& server) { while (true) { auto client = std::make_shared<tcp::iostream>(); server.accept(*client->rdbuf()); std::thread thr([client]() { serveClient(*client, *client); });}} thr.detach(); } }
When the detached thread terminates
How much CPU does the thread consume while the lock() method is running?
When the lock() method is running the OS places the thread in a "blocked" / "waiting" state. So, the thread is not using any CPU at all. So thousands of threads can be running the lock() method and the CPU usage would be 0 (zero)!
Lambda syntax
[/*capture clause*/ ] (/*parameter values inside of scope*/ ) { /*return statement or action being performed*/ }
Which of the following is the correct lambda that can check if a shared queue (shown below) has fewer than 10 elements? namespace pt8 { std::queue<std::string> jobs; }
[](){ return pt8::jobs.size() < 10; }
Which of the following lambdas is equivalent to the following hello method? void hello() { std::cout << "hello"; }
[](){ std::cout << "hello"; }
Which of the following lambdas is equivalent to the following math method? int math(int i, int j) { return (i + j) % i; }
[](int i, int j) { return (i + j) % i; } All you have to do is just change the method name to [] and remove the return type
relative path
a file path that does not include the root element and is used for navigation within the local directory.
absolute path
a path that includes the root element and lists each element in the directory needed to get to the file.
What is a queue in a producer consumer model?
a stack of intermediate results
concurrency
ability of different parts or units of a program, algorithm, or problem to be executed out-of-order or at the same time simultaneously partial order, without affecting the final outcome
System time
amount of time spent by the operating system executing instructions on behalf of the user's program.
Assume a thread t has been detached. Calling join() method on the thread is
an error
argc and argv
argc is the number of arguments passed in and argv is the array of C-strings with the actual commandline arguments
In order to give read and execute permissions to the ower of a file named a.txt, the chmod to be used would be:
chmod u+rx a.txt
A std::lock_guard locks a a given std::mutex in its
constructor
cons of having different threads do different operations
coordinating different groups of threads can be challenging
What should we do if we need separate mutexes on each CS or shared resource?
create a vector of mutexes
thread creation in the OS
created via a syscall
inode
data structure on disk used by Linux file systems
key advantage of multithreading
detached threads make it easy to develop efficient and effective solutions for web-server, database servers, etc.
Which of the following methods is equivalent to the following lambda? [](int i, double d) { return i + d; }
double add(int i, double d) { return i + d; }
goal of one to many/reduction
few amount of intermediate results
What is the structure of an HTTP GET request?
for URL http://ceclnx01.cec.miamioh.edu/~raodm/test.txt GET /~raodm/test.txt HTTP/1.1\r\n Host: ceclnx01.cec.miamioh.edu\r\nConnection: Close\r\n\r\n
what is the goal of the producer thread in a producer consumer model?
generate data(add to queue)
two significant differences between hard links vs. symbolic links
hard link: Limited to files and not directories on the same file system, Actual data is deleted only when all the copies are deleted soft link: Can link to files and directories on different file systems, Link breaks if the original file is deleted.
Serial (sequential) processing
has only one thread, only one task/instruction is processed at a time
auto
infers data type of any variable
functional testing
is the program producing correct results
performance testing
is the program running efficiently
linux command to kill a thread
kill <tid> it is not possible to kill just 1 thread; instead all the threads are killed.
/usr/bin/time
measures runtime characteristics of programs
binary semaphore
mutex lock
Given n items have to be evenly divided between k threads as n ÷ k, an edge condition that arises is when
n % k != 0
Thread Life Cycle
new process -> READY > RUNNING > WAITING -> terminated -transitions through ready(not using the CPU), running(using the CPU), and waiting(blocked, waits for I/O or mutex) stages over and over until they complete - life cycle starts with new and ends with terminated
NI
niceness value of a thread (typically tends to be zero by default) THREADS WITH LOWER VALUES GET HIGHER PRIORITY TO RUN ON THE CPU
Register
part of the CPU with the least capacity, storing limited amounts of instructions and data only immediately before and after processing
lambda [ ]
placeholder for a capture clause which can be used to refer to other variable the lambda with use Ex: [&cout] (int i) { cout << i; } [&cout] () { cout << "lambda"; }
PRI
priority value of a thread (output and is typically 60 to 80)
what is the goal of the consumer thread in a producer consumer model?
process intermediate results (remove from queue)
Assume multiple threads are operating on independent entries of an std::vector - that is, no two threads access the same entries in the vector, which is fine. However, what other method on the vector could cause a race condition?
push_back()
What actions with shared data does not cause a race condition?
reading variables/values (use const)
links
references or aliases to an existing file - avoids copying files -takes up minimal disk space ( just enough to create an inode for the file)
Linux command to increase priority of a thread
renice <niceValue> <tid> to increase priority you need to supply negative values
group id Linux
represents the groups that the user is apart of to enable shared resources
user id Linux
represents the user
When a race condition occurs, a thread causing the race condition will most likely be in
running state
elapsed time
runtime of the program as observed by the user, heavily influenced by other running processes The actual time taken for the program to run
top (Linux)
shows top processes that are using more resources on the machine
Which one of the following data types do not require the use of a std::mutex to ensure MT-safe operations on them?
std::atomic<int>
Which one of the following definition is invalid?
std::atomic<std::string>
The correct reference to a text file named test.txt in the parent directory is:
std::ifstream input("../test.txt");
Given the following code, the correct way to simultaneously lock 2 mutex is: std::mutex m1, m2, m3;
std::lock(m2, m1);
The semaphore that is used to establish a critical section in a C++ program is:
std::mutex
Assume the following method should be run from a separate thread void doIt(std::string param); std::string name = "thready"; Which one of the following shows the correct/preferred code to call the above method from a separate thread, with name as an argument?
std::thread t(doIt, name);
A thread t (shown below) is converted to a background thread by std::thread t(doIt);
t.detach();
how to find linked libraries through the compile output?
the libraries are the words after the -l option to g++
how does synchronization negatively impact performance?
the mutex will be locked and unlocked in a time consuming fashion, the program essentially ends up running just one thread at a time due to very frequent locking
ps -fealL command
the ps command lists the pid and tid (thread ID) of the process and its LWP (aka threads)
std::recursive_mutex
the same thread can repeatedly lock & unlock the mutex
What happens when you orphan a symbolic link (delete the file it refers to)?
the symbolic link exists but is broken/hanging without referring to an actual file.
std::condition notify_one() method
the thread calling this will wake up another thread to let it know some work can be in the queue
chmod command values
u=user, g=group, o=others r=read, w=write, x=execute, - = corresponding permission is not provided, + = corresponding permissions is provided.
std::condition notify_all() method
wakes up all threads waiting on the same condition variable
cp (Linux Command)
• Used to make a copy a file • Duplicate files or directories • cp SOURCE DEST • to create a copy of first.txt and name it second.txt, you use the command "> cp first.txt second.txt"