自制的门锁不锁

kwi*_*ver 4 c++ pthreads

我为一个项目创建了以下代码,我无法访问任何现代C++线程库,如boost.我的愿望是能够让锁在离开范围时自动释放.

共享锁可以正常工作.如果一个线程获得它,则在第一个线程释放它之前,其他任何东西都无法获取它.但是Scoped不起作用.

这是一些显示我的意思的输出.我给每个线程一个不同的名称,让他们用相同的共享锁实例化Scoped锁,打印'获得',睡眠五秒钟,打印'释放',然后离开范围.我没有获得我期望的获得/释放对,而是快速连续获得四个'获得/释放,五秒差距,然后'释放'.我甚至将Scoped中的锁定更改为指针,并在获取之前打印地址,以确保我没有疯狂.看起来它是相同的共享对象,但锁不会阻止多次访问.

Lock '140734928395200'.
acquired: !!!!!
Lock '140734928395200'.
acquired: -------
Lock '140734928395200'.
acquired: ***************
Lock '140734928395200'.
acquired: ##
released: !!!!!
released: -------
released: ***************
released: ##
Run Code Online (Sandbox Code Playgroud)

这是Lock.h的源代码:

#include <pthread.h>
namespace Lock
{
  class Shared
  {
  public:
    Shared()
    {
      ::pthread_mutex_init(&(this->mutex), nullptr);
    }
    ~Shared()
    {
    }
    void acquire()
    {
      ::pthread_mutex_lock(&(this->mutex));
    }
    void release()
    {
      ::pthread_mutex_unlock(&(this->mutex));
    }
  private:
    pthread_mutex_t mutex;
  };
  class Scoped
  {
  public:
    Scoped(Lock::Shared& lock) : lock(lock)
    {
      this->lock.acquire();
    }
    virtual ~Scoped()
    {
      this->lock.release();
    }
  private:
    Lock::Shared& lock;
  };
};
Run Code Online (Sandbox Code Playgroud)

这是我的main.cc文件进行测试.我正在建设:

g++ -std=c++11 -o try -pthread main.cc && ./try
Run Code Online (Sandbox Code Playgroud)

在最新的Ubuntu系统上使用g ++ 4.7.

#include <pthread.h>
#include <iostream>
#include "Lock.h"
#include <unistd.h>
struct data
{
  data(std::string name, Lock::Shared& lock) : name(name), lock(lock) { ; }
  std::string name;
  Lock::Shared& lock;
};
void* doStuff(void* v)
{
  data* d = (data*)v;
  for (int i = 0; i < 5; i++)
  {
    Lock::Scoped(d->lock);
    //d->lock->acquire();
    std::cout << "acquired: " << d->name << std::endl;
    ::sleep(5);
    std::cout << "released: " << d->name << std::endl;
    //d->lock->release();
    ::sleep(1);
  }
}
int main(int argc, char* argv[])
{
  pthread_t fred;
  pthread_t barney;
  pthread_t wilma;
  pthread_t betty;
  Lock::Shared lock;
  data f("##", lock);
  data b("***************", lock);
  data w("-------", lock);
  data e("!!!!!", lock);
  ::pthread_create(&fred, nullptr, doStuff, (void*)&f);
  ::pthread_create(&barney, nullptr, doStuff, (void*)&b);
  ::pthread_create(&wilma, nullptr, doStuff, (void*)&w);
  ::pthread_create(&betty, nullptr, doStuff, (void*)&e);
  ::pthread_join(fred, nullptr);
  ::pthread_join(barney, nullptr);
  ::pthread_join(wilma, nullptr);
  ::pthread_join(betty, nullptr);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

hmj*_*mjd 11

问题是:

for (int i = 0; i < 5; i++)
{
    Lock::Scoped(d->lock);
Run Code Online (Sandbox Code Playgroud)

它创建了一个Lock::Scoped立即构造和销毁的临时数据,因此它没有预期的同步效果.改成:

for (int i = 0; i < 5; i++)
{
    Lock::Scoped lk(d->lock);
Run Code Online (Sandbox Code Playgroud)


NPE*_*NPE 5

问题出在这里:

Lock::Scoped(d->lock);
Run Code Online (Sandbox Code Playgroud)

这会创建一个未命名的临时文件,它会立即超出范围.

要修复,请为其命名:

Lock::Scoped lck(d->lock);
Run Code Online (Sandbox Code Playgroud)