WEB开发网
开发学院软件开发VC Visual C++优化对大型数据集合的并发访问 阅读

Visual C++优化对大型数据集合的并发访问

 2010-08-22 20:47:32 来源:WEB开发网   
核心提示:Timer 类(参见图 2)用于对示例程序测试运行进行计时,它同样是一个极为简单的类,Visual C++优化对大型数据集合的并发访问(3),甚至比 Exception 还要简单,它完全是内联的,这非常方便,因为在真正的多线程应用程序中,因此它只有一个头文件,Timer 在其构造函数中调用 Win32 API GetS

Timer 类(参见图 2)用于对示例程序测试运行进行计时。它同样是一个极为简单的类,甚至比 Exception 还要简单。它完全是内联的,因此它只有一个头文件。Timer 在其构造函数中调用 Win32 API GetSystemTimeAsFileTime 以获取开始时间,然后再次在 stop 方法中调用它来获取结束时间。getXxx 方法将二者之间的差值转换为多种容易感知的单位。

Figure 3 CritSec Class

class CritSec
{
public:
  CritSec();
  ~CritSec()
    { DeleteCriticalSection(&m_critSec); }
  void acquire()
    { EnterCriticalSection(&m_critSec); }
  bool tryAcquire()  // use only on Windows NT or Windows 2000
    { return !!TryEnterCriticalSection(&m_critSec); }
  void release()
    { LeaveCriticalSection(&m_critSec); }
private:
  enum { k_spinCount = 3000ul };
  CRITICAL_SECTION m_critSec;
};
template<class T>
class LockKeeper
{
public:
  LockKeeper(T& t) : m_t(t) { m_t.acquire(); }
  ~LockKeeper() { m_t.release(); }
private:
  T& m_t;
};

图 3

CritSec 类包装了一个临界区(参见图 3)。首先,有些人发现该类是如此简单,以至于他们不相信它有用。然而,第一印象可能是靠不住的。该类之所以重要,有以下三个原因。首先,它使临界区成为面向对象的,从而使其在 C++ 程序中看起来非常合适。这是非常有用的,因为现代 C++ 使用与 C 极为不同的编程风格,因此直接使用 C 函数会强迫程序员频繁改变编程风格,从而导致代码难于阅读和维护。关于这一点,没有比围绕线程同步对象进行的错误处理更为明显的了。CritSec 将 Win32 API 错误转换为异常(使用 Exception 类),从而产生了干净得多的代码。

其次,CritSec(与不久将讨论的 LockKeeper 结合)使临界区具有异常安全性。换句话说,您必须确保在引发异常后,没有任何临界区处于锁定状态。这对于在从错误状态中恢复时避免死锁是非常重要的。

第三,通过在类中包装临界区,您可以使其独立于平台。跨平台的实现超出了本文的范围,但是可以用 Unix 上的 POSIX 线程 API 实现这一相同的 CritSec 类接口。

LockKeeper 模板类(同样参见图 3)与 CritSec 结合使用。我通常不是直接调用 acquire 和 release 方法,而是在堆栈上实例化一个 LockKeeper 实例。构造函数为我调用 acquire 方法,而当 LockKeeper 离开作用域时,析构函数将自动调用 release 方法。这可以消除一个代码行,但更为重要的是,它确保了在锁被占有时引发的异常能够在该异常传播到 LockKeeper 实例的作用域以外时,自动释放该锁。

注意,因为 LockKeeper 是一个模板,所以可以在任何其 acquire 和 release 方法不带参数的类上使用它。这非常方便,因为在真正的多线程应用程序中,将会有许多个这样的类 — Mutex、Semaphore 以及其他类(您不久就将看到)。

Figure 4 Thread Class Definition

class Thread
{
public:
  Thread();
  virtual ~Thread();
  virtual void start();
  virtual bool wait(unsigned long timeout = INFINITE);
  unsigned long getId() const
    { return m_id; }
  HANDLE getHandle() const
    { return m_h; }
protected:
  virtual void run() = 0;
private:
  static unsigned __stdcall entryPoint(void* pArg);
  unsigned long  m_id;
  HANDLE     m_h;
};

图 4

上一页  1 2 3 4 5 6 7 8  下一页

Tags:Visual 优化 大型

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接