poco Mutex(互斥量)

原创 2015年07月10日 11:31:11

作用:
互斥量用于线程间同步。实际上就是锁住某部分指令。
linux 底层的 api 互斥量使用还是很麻烦的。pthread_mutex_init()
pthread_mutex_lock() pthread_mutex_destory()
下面是 Poco 里关于锁的一些实现。

这里写图片描述
要看 Poco::Mutex 所以我们应该去看基类 Poco::MutexImpl 类的实现。


class Foundation_API MutexImpl
{
protected:
    MutexImpl();
    MutexImpl(bool fast);
    ~MutexImpl();
    void lockImpl();
    bool tryLockImpl();
    bool tryLockImpl(long milliseconds);
    void unlockImpl();

private:
    pthread_mutex_t _mutex;
};

MutexImpl () 默认构造函数主要是执行锁的初始化,初始化为可以递归的锁。即同一个线程可以多次进行锁。

    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    pthread_mutex_init(&_mutex, &attr);
    pthread_mutexattr_destroy(&attr);

MutexImpl( bool fast ) 带参数构造函数 主要在设置递归锁的时候判断标志位 fast.如果 fast 为true 那么为不可递归的互斥量。也就是下面将要讲到的 Poco::FastMutex ,如果为 false 那么就是可以递归的互斥量也就是 Poco::Mutex。

    pthread_mutexattr_settype(&attr, fast ? PTHREAD_MUTEX_NORMAL : PTHREAD_MUTEX_RECURSIVE);

主要的方法:

    void lockImpl();//加锁
    bool tryLockImpl();//调用tryLock 函数。成功返回 true,失败返回 false.
    bool tryLockImpl(long milliseconds);//调用pthread_mutex_timeLock() 函数。成功返回 true,失败返回 false.
    void unlockImpl();//解锁。

Poco::Mutex 私有继承 MutexImpl

class Foundation_API Mutex: private MutexImpl

Poco::Mutex 创建的是默认的可以递归的互斥量(需要注意的是同一线成可以多次锁,但是要多次解锁,不同线程不行)。

    void lock();
    void lock(long milliseconds);
    bool tryLock();
    bool tryLock(long milliseconds);//等待获取锁,到达时间没有获取返回 false。
    void unlock();

Poco 最简单的互斥量使用,两个线程,每个线程都先获取锁 2S 之后释放锁。

#include <iostream>
#include <Poco/Mutex.h>
#include <Poco/Thread.h>
#include <unistd.h>

class Worker : public Poco::Runnable
{
public:
    Worker( Poco::Mutex& mtx ):
        _mtx(mtx)
    {
    }

    void run( )
    {
        //获取锁
        _mtx.lock();
        std::cout << Poco::Thread::currentTid() << "   get mtx" << std::endl;
        sleep( 2 );
        _mtx.unlock();
    }

private:
    Poco::Mutex& _mtx;
};


int main( )
{
    Poco::Mutex mtx;

    Poco::Thread th1,th2;
    Worker w1( mtx );
    Worker w2( mtx );

    th1.start( w1 );
    th2.start( w2 );

    th1.join();
    th2.join();
}

可以一个线程先获取了锁,等了两秒之后先获取锁的线程释放了锁,第二个线程才能获取锁。

Poco::FastMutex 继承于 FastMutexImpl
FastMutexImpl 继承于 Poco::MutexImpl

FastMutexImpl 的构造函数指定调用 MutexImpl( true ) 够造一个不能多次锁的普通锁对象。

所以 FastMutex 的功能和 Mutex 的功能一样只是,不能多次锁,否则造成死锁。

在 Poco 互斥量里有一个不得不说的类它就是 Poco::ScopedLock。是一个模板类。它只有3 个 public 方法。
两个构造函数,第一个ScopedLock(M& mutex)是调用传进来的 互斥量的 lock() 方法。第二个ScopedLock(M& mutex, long milliseconds) 是调用传捡来的互斥量的 lock( milliseconds ) 方法。

一个析构函数调用 互斥量的 unlock() 方法。所以使用 Poco::ScopeLock 类的作用是在构造的时候会自动获取锁,在函数退出的时候自动释放锁。
ScopeLock 在Mutex 和 FastMutex 都有实例化。所以使用的锁如果是
Mutex 类型的那么只要
Poco::Mutex::ScopedLock s( _mtx );
Poco::FastMutex::ScopeLock( _mtx );

template <class M>
class ScopedLock
{
public:
    explicit ScopedLock(M& mutex): _mutex(mutex)
    {
        _mutex.lock();
    }

    ScopedLock(M& mutex, long milliseconds): _mutex(mutex)
    {
        _mutex.lock(milliseconds);
    }

    ~ScopedLock()
    {
        try
        {
            _mutex.unlock();
        }
        catch (...)
        {
            poco_unexpected();
        }
    }

下面还是刚刚那个例子。现在改成使用 ScopeLock 来实现。

#include <iostream>
#include <Poco/Mutex.h>
#include <Poco/Thread.h>
#include <unistd.h>

class Worker : public Poco::Runnable
{
public:
    Worker( Poco::Mutex& mtx ):
        _mtx(mtx)
    {
    }

    void run( )
    {
        //获取锁
        Poco::Mutex::ScopedLock s( _mtx );
      std::cout << Poco::Thread::currentTid() << "   get mtx" << std::endl;
        sleep( 2 );
    }

private:
    Poco::Mutex& _mtx;
};


int main( )
{
    Poco::Mutex mtx;

    Poco::Thread th1,th2;
    Worker w1( mtx );
    Worker w2( mtx );

    th1.start( w1 );
    th2.start( w2 );

    th1.join();
    th2.join();
}

从上面代码可以看出来。使用 ScopeLock 可以不需要关心释放锁。所以推荐使用 ScopeLock.

既然有 ScopeLock() 类可以自动帮我我获取锁,退出函数帮我们释放锁。那么有没有哪个类,可以帮我们在自动释放锁,退出函数的时候自动加锁。ScopedUnlock 类就可以实现这样的功能。

应用场景:
比如说当一个线程(A)获取了锁需要从数据库链接池获取一个数据链接,但是此时没有,那么并且需要等到另外的线程(B,C,D)的释放链接信号才能继续执行。但线程B 把链接放回池需要获取锁,这个时候那应该就是 线程 A 在进入阻塞等待之前先释放锁,然后 B 获取了锁,把链接放回去,才发送信号。A 接收到信号之后,激活继续向下 运行,在退出函数的时候重新获取锁。
例子先不写了。下一篇的 Poco::Event 线程间通信可在细述。

转载请注明出处
http://blog.csdn.net/yuhaiyang457288/

Poco::Mutex

Mutex是互斥锁,可以锁住一段代码,用于多线程,保护共有的变量。对Mutex的使用,推荐使用ScopedLock,因为它可以自动解锁,这就是C++析构函数的作用。 void t_scope_m...
  • fym0121
  • fym0121
  • 2012年08月18日 15:19
  • 4495

Poco FastMutex 小结

 各种锁 Mutex 可以重复加的锁,继承了MutexImpl—它在构造的函数内初始化。 FastMutex 与mutex有点类似,不同的...
  • u011235332
  • u011235332
  • 2015年05月25日 11:09
  • 1334

POCO NotificationQueue Sample疑问

为啥打印这一句地方需要加锁互斥? WorkNotification::Ptr pWorkNf = pNf.cast(); if (pWorkNf) { { ...
  • shareyao
  • shareyao
  • 2012年07月29日 11:14
  • 1249

POCO C++库学习和分析 -- 序

POCO C++库学习和分析 -- 序 1. POCO库概述: POCO是一个C++的开源库集。同一般的C++库相比,POCO的特点是提供了整一个应用框架。如果要做C++程序应用框架的快速开发...
  • u010129251
  • u010129251
  • 2015年03月26日 09:32
  • 6116

POCO C++库学习和分析 -- 线程 (三)

POCO C++库学习和分析 -- 线程 (三) 4. 定时器 定时器作为线程的扩展,也是编程时经常会被用到的元素。在程序设计上,定时器的作用是很简单。预定某个定时器,即希望在未来的某个时刻,...
  • zhiweiyang
  • zhiweiyang
  • 2014年08月06日 12:56
  • 388

Mutex(互斥锁)

互斥锁(mutex) 在信号量最后的部分说,当count=1的时候可以用信号量实现互斥。在早期的Linux版本中就是当count=1来实现mutex的。 在2.6.11版本中,如下: typed...
  • longwang155069
  • longwang155069
  • 2016年08月12日 16:22
  • 2670

Linux线程同步-----互斥量(Mutex)

互斥量 与信号处理函数一样,线程在访问全局资源时也会遇到非原子操作导致的冲突(可重入问题). 比如两个线程要对同一个寄存器加1, 并行访问时可能会导致只加了一次. 不可重入操作的特点时,输出不仅依...
  • u013022032
  • u013022032
  • 2016年07月22日 09:28
  • 1811

C++11 mutex方便的自解锁lock_guard

 下面是cpprefrence里的使用mutex的代码。 #include #include #include #include #include #include ...
  • xiaoyafang123
  • xiaoyafang123
  • 2017年01月06日 14:27
  • 3124

lock,Monitor,Mutex的区别

网络上有一很多关于这三个的区别。但是个人的实验跟他们写的有一些出入。把个人的理解写出来,供大家拍砖。 http://www.cnblogs.com/bile/archive/2013/01/08/2...
  • aofengdaxia
  • aofengdaxia
  • 2015年07月06日 10:56
  • 5257

mutex lock

1 数据结构 struct mutex { /* 1: unlocked, 0: locked, negative: locked, possible waiters */ atomic_t c...
  • coldsnow33
  • coldsnow33
  • 2013年12月31日 15:36
  • 1238
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:poco Mutex(互斥量)
举报原因:
原因补充:

(最多只允许输入30个字)