【发布时间】:2018-07-09 06:08:10
【问题描述】:
我来自 Java 背景,并且习惯于使用 Java 的同步进行多线程编程。最近,我开始涉足 C++ 并且不得不处理一些多线程代码。以下是我面临的问题的最小工作示例。
class TxStatus {
private:
int numOperations;
bool commitStatus;
pthread_mutex_t statusLock;
public:
TxStatus() {
this->commitStatus = false;
this->numOperations = 0;
}
void addNewOperation() {
pthread_mutex_lock(&statusLock);
numOperations++;
pthread_mutex_unlock(&statusLock);
}
void operationCompleted() {
pthread_mutex_lock(&statusLock);
numOperations--;
pthread_mutex_unlock(&statusLock);
}
void commit() {
this->commitStatus = true;
}
};
class TxManager {
private:
unsigned long long globalFrontier;
unsigned long long txId;
pthread_mutex_t gfLock;
pthread_mutex_t txIdLock;
std::map<unsigned long long, TxStatus> txStatusMap;
public:
TxManager() {
pthread_mutex_lock(&gfLock);
globalFrontier = 1;
pthread_mutex_unlock(&gfLock);
pthread_mutex_lock(&txIdLock);
txId = 1;
pthread_mutex_unlock(&txIdLock);
}
unsigned long long beginNewTx() {
pthread_mutex_lock(&txIdLock);
unsigned long long newId = txId;
txId++;
pthread_mutex_unlock(&txIdLock);
TxStatus statusObj;
txStatusMap.insert(std::make_pair(newId,statusObj));
return newId;
}
void addUnflushedOperation(unsigned long long txId) {
txStatusMap[txId].addNewOperation();
}
void markOperationAsFlushed(unsigned long long txId) {
txStatusMap[txId].operationCompleted();
}
void markCommitted(unsigned long long txId) {
txStatusMap[txId].commit();
}
};
void * thread( void *args){
TxManager txManager;
fprintf(stderr,"Inside thread");
unsigned long long newTxId = txManager.beginNewTx();
fprintf(stderr,"Tx Started: %d", newTxId );
txManager.addUnflushedOperation(newTxId);
pthread_exit(NULL);
}
int main(){
pthread_t tx_thread;
fprintf(stderr,"Inside main");
int ret = pthread_create(&tx_thread, NULL, thread, NULL);
if (ret != 0)
{
fprintf(stderr,"Error launching thread");
}else{
fprintf(stderr,"Thread launched successfully");
}
if (pthread_join(tx_thread, NULL) != 0)
{
fprintf(stderr,"Join pthread failed");
}
return 0;
}
线程已成功启动,但我从未看到线程本身执行的函数(即 thread())的打印结果之一。如果我删除了 join 调用,那么程序会在 main 方法中打印语句后终止。
【问题讨论】:
-
据我所知,您没有初始化互斥锁,您正在锁定不需要锁定的东西,而无法锁定需要锁定的东西。您可以访问
C++11和std::thread吗? -
@Galik 您能否详细说明您所说的“您正在锁定不需要锁定的东西而无法锁定需要锁定的东西”时的意思?
-
例如,在
beginNewTx()中,您锁定了对txId的访问,这表明该函数将从多个线程中调用,但您不锁定对txStatusMap的访问,如果从多个线程修改则需要锁定线程。 -
另外,在
TxManager的构造函数中,您在初始化其成员时会锁定访问权限,但不可能有多个线程创建同一个对象,因此您无需锁定对其的访问权限构造函数初始化期间的成员。