简介
策略锁设计模式参数化了保护组件的临界区并发访问的同步机制。换句话说,当一个对象需要在另一个不同线程中创建的数据时,它需要锁定临界区以访问数据。想象一下当一个线程中的对象正在写共享数据,而同时另一个不同的对象正在另一个线程中读取数据的结果。你永远也不知道结果究竟如何。。。。。。。
一个临界区可以被例如创建使用一个互斥量来锁定。有多种方法来创建和获取和释放一个互斥量。然而,最最重要的是按照下面的三步小心的避免锁定失败以及思索。这个模式负责这三个行动。除此之外,它在一个专门的对象中封装了Windows的互斥量方法
详细信息
详细信息可以翻阅这本书:《Pattern-Oriented Software Architecture (Volume 2).》
什么时候使用这个模式?
使用这个模式的时机如下:
- 你想要守护一个临界区
- 你想要使用mutex保持一致性
- 你想要一个更加可读的代码
- 你不想要实现一遍遍的实现mutex
- 你不想产生死锁
使用策略锁模式
这个模式由三部分组成:
Part1:封装Windows的Mutex方法
Part2:创建,获取和释放Mutex的职责
Part3:可锁定对象的接口。
UML类图
Sensor类被用来作为一个例子。
Lock:windows的Mutex调用的封装器
Guard:负责获取和释放Muex
ILockable:负责提供可锁定对象的共享数据的锁定接口。
时序图
下面是时序图,有三种使用这种模式的方法:
Usage 1
Usage 2
Usage 3
**
如何使用代码
用法一
创建一个Mutex,获取,然后释放
头文件.h如下:
private:
Lock m_lock;
unsigned int m_count;
实现文件.cpp:
m_lock.Take( );
m_count++; // critical section
m_lock.Release( ); // make sure you release it!
用法2(多态)
在这种方法中,传一个多态锁对象给guard的构造函数然后定义一个这个所对象的实例作为其一个私有数据成员。
头文件.h:
private:
Lock m_lock;
unsigned int m_count;
实现文件.cpp:
Guard guard( m_lock ); // no release is needed
m_count++; // critical section
用法3(参数化)
这种方法中,定义一个模板的guard类,由锁的类型参数化,获取和释放都是自动的。派生你的对象自ILockable接口。
头文件.h:
class Sensor : public ILockable
{
public:
// constructor
Sensor( );
实现ILockable的方法:
private:
/**
* @see ILockable::Take().
*
* @since <30 01 2009 >
*/
virtual void Take( );
/**
* ILockable::Release().
*
* @since <30 01 2009 >
*/
virtual void Release( );
我已经选择锁定Sensor对象作为例子。
实现文件.cpp:
Guarder< ILockable > guarder( *this ) ;
头文件.h:
private:
Lock m_lock;
实现文件.cpp:
Guarder< Lock > guarder( m_lock ) ;
Strategized Locking Pattern
http://www.codeproject.com/Articles/33241/Strategized-Locking-Pattern
The Strategized Locking design pattern parameterized synchronization mechanisms protect a component’s critical section from concurrent access.
Introduction
The Strategized Locking design pattern parameterized synchronization mechanisms protect a component’s critical section from concurrent access. In other words, when an object requires data which is created within a different thread, it is necessary to lock the critical sections for data access. Just imagine the result of a data when an object within a thread is writing the shared data, and simultaneously a different object is reading this data from a different thread. You never know the result…
A critical section can be locked for example by creating and using a Mutex. There are different ways to create, take and release a Mutex. However, it is of utmost importance to follow these three steps carefully to prevent lock failures and/or deadlocks. This pattern holds the responsibility for these three actions. Moreover, it wraps the Windows Mutex methods within a dedicated object.
Detailed Information
Detailed information can be found in this book: Pattern-Oriented Software Architecture (Volume 2).
When to Use this Pattern?
Use this pattern if:
You want to guard a critical section
You want to be consistent with using mutex
You want a more readable code
You don’t want to implement a mutex over and over again
You don’t want to create a deadlock
Using the Strategized Locking Pattern
This pattern exists of three parts:
Part 1: Wrapper around the Windows Mutex methods
Part 2: The responsibility for creating, taking and releasing the Mutex
Part 3: The interface for objects which are lockable
UML Class Diagram
The Sensor class is used as an example.
SLP_pattern_main.jpg
Lock: The wrapper for the Windows Mutex calls
Guard: Responsible for taking and releasing the Mutex
ILockable: Responsible for providing the interface for locking shared data within lockable objects
Sequence Diagram
There are 3 ways to use this pattern:
Usage 1
Usage 2
Usage 3
**
How to Use the Code
**
Usage 1
Create a Mutex, take it, and release it.
The header file *.h:
Hide Copy Code
private:
Lock m_lock;
unsigned int m_count;
The implementation file *.cpp:
Hide Copy Code
m_lock.Take( );
m_count++; // critical section
m_lock.Release( ); // make sure you release it!
Usage 2 (Polymorphism)
In this approach, pass a polymorphic lock object to the guard’s constructor and define an instance of this lock object as a private data member.
The header file *.h:
Hide Copy Code
private:
Lock m_lock;
unsigned int m_count;
The implementation file *.cpp:
Hide Copy Code
Guard guard( m_lock ); // no release is needed
m_count++; // critical section
Usage 3 (Parameterized)
In this approach, define a template guard class that is parameterized by the type of lock that will be acquired and released automatically. Inherit your object from the ILockable interface.
Hide Copy Code
class Sensor : public ILockable
{
public:
// constructor
Sensor( );
Implement the ILockable methods:
Hide Copy Code
private:
/**
* @see ILockable::Take().
*
* @since <30 01 2009 >
*/
virtual void Take( );
/**
* ILockable::Release().
*
* @since <30 01 2009 >
*/
virtual void Release( );
I have selected to lock the Sensor object as an example.
The implementation file *.cpp:
Hide Copy Code
Guarder< ILockable > guarder( *this ) ;
or the header file *.h:
Hide Copy Code
private:
Lock m_lock;
The implementation file *.cpp:
Hide Copy Code
Guarder< Lock > guarder( m_lock ) ;