线程锁问题,但是为什么累加还是不对,设的是20次运行
.h函数//
#ifndef B1EventAction_h
#define B1EventAction_h 1
#include "G4UserEventAction.hh"
#include "globals.hh"
#include <mutex>
/// Event action class
///
namespace B1
{
class RunAction;
class EventAction : public G4UserEventAction
{
public:
EventAction(RunAction* runAction);
~EventAction() override;
void BeginOfEventAction(const G4Event* event) override;
void EndOfEventAction(const G4Event* event) override;
private:
std::mutex myLock; // 用于保护需要同步的资源
G4int TotalCount= 0;
G4int TempCount= 0;
};
}
//
include "G4RunManager.hh"
#include <mutex>
using namespace std;
namespace B1
{
EventAction::EventAction(RunAction* runAction)
: fRunAction(runAction)
{}
EventAction::~EventAction()
{}
void EventAction::BeginOfEventAction(const G4Event*)
{
fEdep = 0.;
}
void EventAction::EndOfEventAction(const G4Event* aEvent)
{
// myLock.lock();
std::lock_guard<std::mutex> lock(myLock);// 加锁
TotalCount ++;
TempCount ++;
G4cout<< "*!!!!!!!!!!!!!!!!!!******* EndOfEventAction ,TotalCount : "<< TotalCount <<G4endl;
// myLock.unlock();
}
}
问题出在锁的使用上。在BeginOfEventAction函数中,你没有对锁进行解锁操作。这导致了在EndOfEventAction函数中尝试加锁时出现了死锁的情况。解决这个问题的方法是在BeginOfEventAction函数中添加解锁操作。
修改后的代码如下:
void EventAction::BeginOfEventAction(const G4Event*)
{
fEdep = 0.;
myLock.unlock(); // 解锁
}
void EventAction::EndOfEventAction(const G4Event* aEvent)
{
std::lock_guard<std::mutex> lock(myLock);// 加锁
TotalCount ++;
TempCount ++;
G4cout<< "*!!!!!!!!!!!!!!!!!!******* EndOfEventAction ,TotalCount : "<< TotalCount <<G4endl;
}
请注意,在BeginOfEventAction函数中添加解锁操作后,你就不再需要在EndOfEventAction函数中手动加锁和解锁了。使用std::lock_guard<std::mutex>可以确保在函数结束时自动释放锁,避免了手动加锁和解锁可能出现的错误。 根据你提供的代码,我发现有几个问题可能会导致累加结果不正确:
1. 在 EventAction 类中,TotalCount 和 TempCount 变量没有初始化为0。请确保在构造函数中将它们初始化为0。
G4int TotalCount = 0;
G4int TempCount = 0;
2. 在 EndOfEventAction 函数中,你使用了 std::lock_guard<std::mutex> lock(myLock) 来进行加锁操作。这是正确的做法,它会在作用域结束时自动释放锁。
3. 你使用 myLock.lock() 和 myLock.unlock() 进行手动加锁和解锁的尝试,但是这会导致问题,因为你已经使用了 std::lock_guard 来管理锁。所以在 EndOfEventAction 函数中,你可以将 myLock.lock() 和 myLock.unlock() 的代码注释掉,只保留 std::lock_guard<std::mutex> lock(myLock) 即可。
void EventAction::EndOfEventAction(const G4Event* aEvent){
std::lock_guard<std::mutex> lock(myLock);// 加锁
TotalCount++;
TempCount++;
G4cout << "*!!!!!!!!!!!!!!!!!!******* EndOfEventAction, TotalCount: " << TotalCount << G4endl;
}
通过以上修改,应该能够正确地累加 TotalCount 和 TempCount 的值。请重新测试你的代码,并检查输出结果是否正确。
如果问题仍然存在,请提供更多关于你的代码和问题的详细信息,我将尽力帮助你解决。
如果问题已经解决,请设置最佳答案 根据你提供的代码,我发现在EndOfEventAction函数中,每个事件结束后都会增加TotalCount和TempCount的值。你使用了互斥锁来保护这两个变量,确保在多线程环境下的安全访问。但是,问题可能出现在主函数中的调用部分,你可能需要多次运行线程来达到累加的效果。
你可以尝试在主函数中创建多个线程,并在每个线程中执行事件的开始和结束操作。这样才能触发多个事件,达到累加的目的。下面是一种可能的修改示例:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;// 用于保护需要同步的资源
int totalCount = 0;
int tempCount = 0;
void EndOfEventAction() {
std::lock_guard<std::mutex> lock(mtx);// 加锁
totalCount++;
tempCount++;
std::cout << "*!!!!!!!!!!!!!!!!!!*** EndOfEventAction, TotalCount: " << totalCount << std::endl;
// 在作用域结束时自动解锁
}
int main() {
const int numThreads = 20;
std::thread threads;
for (int i = 0; i < numThreads; ++i) {
threads = std::thread(EndOfEventAction);
}
for (int i = 0; i < numThreads; ++i) {
threads.join();
}
return 0;
}
在上述代码中,我们通过创建多个线程来模拟多个事件的结束操作。每个线程执行EndOfEventAction函数,并在其中加锁、累加计数并输出结果。在主函数中,我们创建了20个线程并等待它们完成。
请注意,这只是一种可能的修改方式。你可能还需要根据实际需求进行调整。希望这次回答能够解决你的问题。如果还有其他问题,请随时提问。
球一个最佳答案谢谢啦!这对我非常重要!{:10_254:}{:10_254:}{:10_254:}
根据您提供的代码,我注意到您的累加计数器可能没有正确工作的原因是,每次执行EndOfEventAction函数时,您都会创建一个新的EventAction对象,而每个对象都有自己的TotalCount和TempCount变量。这导致了每次累加都是从零开始。
为了解决这个问题,您可以将TotalCount和TempCount声明为静态成员变量,这样它们将在所有EventAction对象之间共享。此外,您需要在类外定义这些静态成员变量。下面是修改后的代码示例:
.B1EventAction.h
#ifndef B1EventAction_h
#define B1EventAction_h 1
#include "G4UserEventAction.hh"
#include "globals.hh"
#include <mutex>
namespace B1 {
class RunAction;
class EventAction : public G4UserEventAction {
public:
EventAction(RunAction* runAction);
~EventAction() override;
void BeginOfEventAction(const G4Event* event) override;
void EndOfEventAction(const G4Event* event) override;
private:
static std::mutex myLock; // 用于保护需要同步的资源
static G4int TotalCount;
static G4int TempCount;
};
}
#endif
.B1EventAction.cc
#include "B1EventAction.hh"
#include "B1RunAction.hh"
#include "G4Event.hh"
#include "G4RunManager.hh"
#include "G4UnitsTable.hh"
#include <mutex>
using namespace B1;
std::mutex EventAction::myLock;
G4int EventAction::TotalCount = 0;
G4int EventAction::TempCount = 0;
EventAction::EventAction(RunAction* runAction) : G4UserEventAction(), fRunAction(runAction) {}
EventAction::~EventAction() {}
void EventAction::BeginOfEventAction(const G4Event*) {
fEdep = 0.;
}
void EventAction::EndOfEventAction(const G4Event* aEvent) {
std::lock_guard<std::mutex> lock(myLock); // 加锁
TotalCount++;
TempCount++;
G4cout << "*!!!!!!!!!!!!!!!!!!*** EndOfEventAction, TotalCount: " << TotalCount << G4endl;
}
这样修改后,TotalCount和TempCount将作为类的静态成员变量,被所有的EventAction对象共享。加锁操作也会确保在修改这些变量时的线程安全性。
希望这次回答能够解决您的问题。如果还有其他问题,请随时提问。
如果回答对你有帮助,请给我一个最佳答案!{:10_254:}{:10_254:}{:10_254:}
学习编程中的Ben 发表于 2023-8-9 21:57
根据您提供的代码,我注意到您的累加计数器可能没有正确工作的原因是,每次执行EndOfEventAction函数时,您 ...
大哥,你就是个小天才,我成功了,谢谢
页:
[1]