classCAPABILITY("mutex") MutexLock : public noncopyable { public: MutexLock() : holder_(0) { MCHECK(pthread_mutex_init(&mutex_, NULL)); // 宏函数MCHECK, 用于检查库函数/系统调用的返回值 } ~MutexLock() { assert(holder_ == 0); MCHECK(pthread_mutex_destroy(&mutex_)); } // must be called when locked, i.e. for assertion boolisLockedByThisThread()const// 断言 当前调用线程持有锁, 失败返回false, 不会导致程序终止 { return holder_ == CurrentThread::tid(); } voidassertLocked()constASSERT_CAPABILITY(this)// 断言 调用线程持有锁, 会导致程序终止, 用于debug { assert(isLockedByThisThread()); }
// internal usage
/** * lock mutex_ and check lock status. * assign current thread's tid as the lock's holder */ voidlock()ACQUIRE() { MCHECK(pthread_mutex_lock(&mutex_)); assignHolder(); } /** * unassign the lock's holder, then unlock mutex_. */ voidunlock()RELEASE() { unassignHolder(); MCHECK(pthread_mutex_unlock(&mutex_)); } /* non-const, because return a pointer to class's (private) data */ pthread_mutex_t* getPthreadMutex() { return &mutex_; }
private: friendclassCondition;
/* give up the MutexLock */ classUnassignGuard : public noncopyable // 用于放弃锁, 如条件变量中需要放弃锁时可用到 { public: explicitUnassignGuard(MutexLock& owner) : owner_(owner) { owner_.unassignHolder(); // clear lock owner_ holder } ~UnassignGuard() { owner_.assignHolder(); // set current thread as the lock holder }
private: MutexLock& owner_; // 互斥锁对象引用 }; /** * set current thread as the lock holder * by assigning current thread's tid to holder */ voidassignHolder() { holder_ = CurrentThread::tid(); // 设置锁的持有线程tid为当前线程tid } /** * clear the lock holder */ voidunassignHolder()// 清除锁的持有线程tid { holder_ = 0; }
// 多线程核心测试部分 // multi-thread invoke threadFunc try to get the same mutex at the same time for (int nthreads = 0; nthreads < kMaxThreads; ++nthreads) { std::vector<std::unique_ptr<Thread>> threads; g_vec.clear(); g_threadfunc_count = 0; start = Timestamp::now(); for (int i = 0; i < nthreads; ++i) { threads.emplace_back(newThread(&threadFunc)); threads.back()->start(); }
for (int i = 0; i < nthreads; ++i) { threads[i]->join(); } printf("%d thread(s) with lock %f seconds\n", nthreads, timeDifference(Timestamp::now(), start)); printf("g_threadfunc_count = %d\n", g_threadfunc_count); } return0; }