2. THREAD-SAFE
• In multi-threaded programming, threads share resources.
• It may lead to race condition.
• A piece of code is thread-safe if it functions correctly during simultaneous
execution by multiple threads.
• Synchronization is the most widely used method to achieve thread-safe.
• Lock is a kind of synchronization.
3. REENTRANTLOCK
• A lock is acquired via lock() and released via unlock().
• If another thread has already acquired the lock, subsequent calls to lock() pause
the current thread until the lock has been unlocked.
• Only one thread can hold the lock at any given time.
• tryLock() is an alternative to lock().
4. READWRITELOCK
• This type of lock maintains a pair of locks for read and write access.
• Read-lock can be held simultaneously by multiple threads as long as no threads
hold the write-lock.
• Improve performance and throughput in situations that reads are more frequent
than writes.
6. STAMPEDLOCK
• Also support read and write locks.
• locking methods return a stamp.
• These stamps are used to release a lock, to check if the lock is still valid or to
convert the mode.
• Main features of StampedLock compared to ReadWriteLock is mode conversion
and optimistic read.
7. STAMPEDLOCK
MODE CONVERSION
When and how to convert mode:
• You acquired the write lock and wrote something and you want to read in the
same critical section, use tryConvertToReadLock(long stamp).
• You acquired the read lock, and after a successful read, you wanted to change the
value, use tryConvertToWriteLock(long stamp).
8. STAMPEDLOCK
OPTIMISTIC READ
StampedLock has 3 modes of access: Read, Write, Optimistic Read.
• Read, Write: equivalent to ReadWriteLock while returning a stamp.
• Optimistic Read: doesn't prevent another thread from getting a write lock, which
will make the optimistic read lock stamp's invalid.
9. SPINLOCK
• A lock which causes a thread trying to acquire it to simply wait in a loop ("spin")
while repeatedly checking if the lock is available.
• Efficient if threads are likely to be blocked for only short periods.
11. SEMAPHORE
• Locks usually grant exclusive access to variables or resources.
• Semaphores are capable of maintaining whole sets of permits.
• Useful in scenarios where you have to limit the amount concurrent access to
certain parts of your application.
12. DISTRIBUTED LOCK
• Common problems : how to ensure that only one
process across a fleet of servers acts on a resource:
• processes may pause for arbitrary lengths of time
• packets may be arbitrarily delayed in the network
• clocks may be arbitrarily wrong
14. DISTRIBUTED LOCK
• Safety and Liveness guarantees
1. Safety property: Mutual exclusion. At any given moment, only one client can
hold a lock.
2. Liveness property A: Deadlock free. Eventually it is always possible to acquire
a lock, even if the client that locked a resource crashes or gets partitioned.
3. Liveness property B: Fault tolerance. As long as the majority of Redis nodes
are up, clients are able to acquire and release locks.
15. REDLOCK
• In order to acquire the lock, the client performs the following
operations:
• 1. Get the current time.
• 2. … All the steps needed to acquire the lock …
• 3. Get the current time, again.
• 4. Check if we are already out of time, or if we acquired the lock fast enough.
• 5. Do some work with your lock.
- Race condition: show example
- Thread-safe: In particular, it must satisfy the need for multiple threads to access the same shared data, and the need for a shared piece of data to be accessed by only one thread at any given time.
- Trylock: it tries to acquire the lock without pausing the current thread.
- Reentrant means that locks are bound to the current thread. A thread can safely acquire the same lock multiple times without running into deadlocks.
- The idea behind read-write locks is that it's usually safe to read mutable variables concurrently as long as nobody is writing to this variable.
- The idea behind read-write locks is that it's usually safe to read mutable variables concurrently as long as nobody is writing to this variable.
- ReadWriteLock is good, but it has some severe issues with starvations if not handled properly. For example, a number of reads but very few writes can cause the writer thread to fall into starvation.
- Note: StampedLock is not reentrant, so each call to acquire the lock always returns a new stamp and blocks if there's no lock available, even if the same thread already holds a lock, which may lead to deadlock.
- Note: Converting methods do not block and may return the stamp as zero, which means these methods' calls were not successful.
- If using optimistic read, always check if the stamp is valid using the lock.validate(stamp) before reading.
- Those instructions usually are much faster than synchronizing via locks.
- Thread will access data from memory address and compare the current value with current expected value. If they match It will update the variable to new value. Obviously If multiple threads try making this operation simultaneously only one thread will succeed and others will fail. But other threads will not block instead invoker can continue with other operation or try the same again with failing threads. So this provides a lot better performance .
- A kind of busy waiting.
- Because they avoid overhead from operating system process rescheduling or context switching.
- A kind of busy waiting.
- Because they avoid overhead from operating system process rescheduling or context switching.