Concurrency Flashcards
What is a synchronous operation?
- Synchronisity is when you make a request whether this is a network call, request to read from disk, request to print, etc, there is a process and a thread that is waiting from the disk such as i/o controller.
- When you maka a request to do some process to talk to something, synchronous execution and waiting and blocked despite us not doing any work.
Important Differences between Concurrent Programming vs. Distributed Systems
- Underlying primitives are different: shared memory vs. message passing
- Distributed systems experience communications failure
- Distributed systems (may) experienced unbounded latency (due to system degradation, etc.)
- Difficulty of distributed time
What is concurrency?
- Computers doing many things at the same time, that is concurrency.
- Example: Writing back data buffered in memory to a hard disk while the program continues to execute
- You have 2 CPUs executing code at the same time
- 1 CPU you have direct memory access data between memory and i/o devices at the same time
- 1 CPU is running the code and continuing the program
- You have 2 CPUs executing code at the same time
How does concurrency occur in a computer system?
Processes, threads, interrupts, hardware
How do we control concurrency?
- Mutual exclusion (locks and semaphores)
- Condition synchronization
- Lock-free programming
Python dictionary is not thread safe, why?
- Python has a GIL (global interpreter lock), a process can only execute one python bytecode at a time regardless of how many threads it has. This means inserting/updating/reading a key for a map is thread-safe, which also means python’s get/put functions for dictionary’s are atomic
- Well
\_\_hash\_\_
method in Python has multiple bytecodes, which means its not atomic therefore get and put are not thread-safe in Python, in the sense they don’t cause crashes or garbage values, so you can still have race conditions.
- Well
- Multiple threads trying to update DIFFERENT keys to the same dictionary will not be concurrent in Python. In Java you don’t have the GIL issue so multiple threads can update different keys in ConcurrentHashMap at the same time (which doesn’t happen but its possible.)
ConcurrentHashMap shards the set of keys and locks for each shard. Each shard can be read concurrently but only one thread can write at a time.
What data structure would you use to communicate data between threads?
Use theQueuemodule’s Queue data type as the preferred way to communicate data between threads. Otherwise, use the threading module and its locking primitives. Learn about the proper use of condition variables so you can usethreading.Conditioninstead of using lower-level locks.
What is Thread Safety?
Thread safety means that two threads cannot modify the same object at the same time, thereby leaving the system in an inconsistent state.
Thread Safety?
Thread Safety
- Concurrent programming isn’t about threads or locks. Building concurrent programs require the correct use of threads and locks, but again these are just mechanisms, a means to an end.
- Writing thread-safe code at its core is about managing access to state, and in particular, shared mutable state.
- By shared we mean → a variable that can be accessed by multiple threads
- By mutable → we mean the value can change during its lifetime
- We can talk about code, but what we are really trying to do is protect data from uncontrolled concurrent access.
- Whether an object needs to be thread-safe depends on whether it will be ac-
cessed from multiple threads. This is a property of how the object is used in a
program, not what it does. Making an object thread-safe requires using synchro-
nization to coordinate access to its mutable state; failing to do so could result in
data corruption and other undesirable consequences.
- Whether an object needs to be thread-safe depends on whether it will be ac-
-
If multiple threads access the same mutable state wihotu appropriate synchornization, your program is broken
-
Fix it by
- Dont share the state variable across threads
- Make the state variable immutable, or
- Use synchornization whenever accessing the state variable
-
Fix it by
What is a race condition?
A race condition occurs when the correctness of a computation depends
on the relative timing or interleaving of multiple threads by the runtime; in other
words, when getting the right answer relies on lucky timing.4 The most common
type of race condition is check-then-act, where a potentially stale observation is
used to make a decision on what to do next.
Race condition example is reading data that is stale and taking action on that read
What is the reason to use concurrency?
- CPU intensive tasks: You can speed up algorithms by executing parts in parallel
- I/O: Other parts of the program can run while we are waiting for I/O Response
- Reactivity: White a GUI application executes some lengthy operation, the application should still accept user interaction and not block
Deadlock
A deadlock happens if execution threads mutually claim resources that the other execution threads need (need to meet 4 of the Coffman conditions)
- Example
- Both thread 1 and thread 2 need resources A and B to finish a task
- Thread 1 already holds resource A and wants resource B to complete its task
- Thread 2 already hold resource B and wants resource A to complete its task
- ⇒ Deadlock!
What is a lock?
Its a synchronization primitive that allows us to block out areas in our code so only 1 thread can have access for some critical section in our code, which involves that thread mutating shared state between threads. It is used to avoid race conditions when we have multiple threads that share state and there is logic to mutate that shared state, so locks come in to guard against race conditions, such as a thread reading stale data and taking action on it. Typically we will guard sections in code for both read/writes for this shared mutable state.
Threads can work together. What if a thread reads a result before another thread writes it?
Threads need to synchronize with each other.
A Barrier is a point in the program where threads stop and wait. When all threads have reached the barrier, they can proceed.
Use when you want for a series of threads to hit some point before the overall task can proceed.
We block until we hit the number of threads needed to then pass the barrier, until then we block and wait until we hit the thread count we need for the barrier.