Download presentation
Presentation is loading. Please wait.
Published byPrudence Lamb Modified over 9 years ago
1
Concurency and synchronisation patterns based on Pattern-Oriented Software Architecture, Patterns for Concurrent and Networked Objects, Volume 2 by Douglas Schmidt, Michael Stal, Hans Rohnert and Frank Buschmann
2
Design Pattern A design pattern is a general reusable solution to a commonly occurring problem in software design.
3
Agenda Synchronisation patterns – Scoped Locking – Strategized Locking – Thread-Safe Interface Concurency patterns – Active Object – Leader/Followers
4
Scoped Locking The Scoped Locking C++ idiom ensures that a lock is acquired when control enters a scope and released automatically when control leaves the scope, regardless of the return path from the scope.
5
Scoped Locking - Implementation class Thread_Mutex_Guard { public: Thread_Mutex_Guard (Thread_Mutex &lock) : lock_ (&lock), owner_ (false) { lock_->acquire (); owner_ = true; } ~Thread_Mutex_Guard () { if (owner_) lock_->release (); } private: Thread_Mutex *lock_; bool owner_; Thread_Mutex_Guard (const Thread_Mutex_Guard&); void operator= (const Thread_Mutex_Guard &); };
6
Scoped Locking – Explicit Accessors class Thread_Mutex_Guard { public: Thread_Mutex_Guard (Thread_Mutex &lock) : lock_ (&lock), owner_ (false) { acquire (); } ~Thread_Mutex_Guard () { release (); } void acquire () { lock_->acquire (); owner_ = true; } void release () { if (owner_) { owner_ = false; lock_->release (); } private: Thread_Mutex *lock_; bool owner_; };
7
Scoped Locking – Example class Test { public: void test_function_1 { Thread_Mutex_Guard quard(&lock_); //do something } void test_function_2 { Thread_Mutex_Guard quard(&lock_); //do something } private: Thread_Mutex lock_; };
8
Scoped Locking - Consequences Benefits – Increased robustness Liabilities – Potential for deadlock when used recursively. – Limitations with language-specific semantics. Thread_Mutex_Guard guard (&lock_); Table_Entry *entry = lookup_or_create (path); if (entry == 0) pthread_cancel(pthread_self()); – Excessive compiler warnings
9
Strategized Locking Similar to Scoped Locking but pass template or polymorphic lock object to the guard constructor. class Lock { public: virtual void acquire () = 0; virtual void release () = 0; };
10
Strategized Locking - Example class Lock { public: virtual void acquire () = 0; virtual void release () = 0; }; class Thread_Mutex_Lock : public Lock { public: virtual void acquire () { lock_.acquire (); } virtual void release () { lock_.release (); } private: Thread_Mutex lock_; };
11
Scoped Locking – Example class Test { public: void test_function_1 { Thread_Mutex_Guard quard(&lock_); //do something } void test_function_2 { Thread_Mutex_Guard quard(&lock_); //do something } private: Thread_Mutex lock_; };
12
Strategized Locking - Example template class quard_t { private: boollocked; T& protector; guard_t(const guard_t& orig); public: guard_t(T& _protector) : protector(_protector), locked(false) { protector.acquire(); } virtual ~guard_t() { if (locked) protector.release(); } void release() { if (locke) { protector.release(); locked = false;} }; void acquire() {protector.acquire(); locked = true;}; };
13
Scoped Locking – Example class Test { public: void test_function_1 { quard quard(&lock_); //do something } void test_function_2 { quard quard(&lock_); //do something } private: Thread_Mutex lock_; };
14
Strategized Locking - Example typedef File_Cache Content_Cache;
15
Strategized Locking - Consequences Benefits – Enhanced flexibility and customization. – Decreased maintenance effort for components. – Improved reuse. Liabilities – Obtrusive locking. – Over-engineering.
16
Thread-Safe Interface The Thread-Safe Interface design pattern minimizes locking overhead and ensures that intra-component method calls do not incur 'self- deadlock' by trying to reacquire a lock that is held by the component already.
17
Thread-Safe Interface Example template class File_Cache { public: const void *lookup (const string &path) const { Guard guard (lock_); return lookup_i (path); } void insert (const string &path) { Guard guard (lock_); insert_i (path); } private: mutable LOCK lock_; const void *lookup_i (const string &path) const { const void *file_pointer = check_cache_i(path); if (file_pointer == 0) { insert_i (path); file_pointer = check_cache_i (path); } return file_pointer; } const void *check_cache_i (const string &) const {} void insert_i (const string &) {}
18
Consequences Benefits – Increased robustness. – Enhanced performance. – Simplification of software. Liabilities – Additional indirection and extra methods. – Potential deadlock. – Potential for misuse. – Potential overhead.
19
Active Object The Active Object design pattern decouples method execution from method invocation to enhance concurrency and simplify synchronized access to objects that reside in their own threads of control.
20
Active Object Methods invoked on an object concurrently should not block the entire process, Synchronized access to shared objects should be simple, Applications should be designed to transparently leverage the parallelism available on a hardware/software platform
21
Active Object
23
Consequences Benefits – Enhance application concurrency and simplify synchronization complexity, – Transparently leverage available parallelism, – Method execution order can differ from method invocation order Liabilities – Performance overhead. – Complicated debugging.
24
Leader/Followers The Leader/Followers design pattern provides a concurrency model where multiple threads can efficiently demultiplex events and dispatch event handlers that process I/O handles shared by the threads.
25
Leader/Followers Efficient demultiplexing of I/O handles and threads, Minimize concurrency- related overhead, Prevent race conditions
26
Leader/Followers
30
Consequences Benefits – Performance enhancements. It enhances CPU cache affinity and eliminates unbound allocation and data buffer sharing between threads, It minimizes locking overhead by not exchanging data between threads, It can minimize priority inversion because no extra queuing is introduced in the server, It does not require a context switch to handle each event – Programming simplicity. Liabilities – Implementation complexity. – Lack of flexibility. – Network I/O bottlenecks.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.