【问题标题】:Pthread_mutex_lock returning access errorpthread_mutex_lock 返回访问错误
【发布时间】:2012-10-31 19:02:32
【问题描述】:

我正在编写一个读取和处理大量数据的程序。为了加快进程,我使用 C++ 的 Pthreads 库实现了多线程读取/处理。但是,当我在互斥体上调用 pthread_mutex_lock(&lock1) 时,我的程序出错,在 lock1 的地址上给我一个“访问冲突读取位置”错误。我需要在一个类的方法上运行这些线程,这需要一些操作才能在 pthread 库的限制范围内完成,而我在操作的某个地方犯了错误。以下是我的代码的缩写版本,对不起 tl;dr。在不遗漏任何对多线程至关重要的部分的情况下尽可能缩短它:

#include "pthread.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>


/*Ideally I need to create one instance of this object that has the run_stuff method 
being executed by two different threads.  I need both threads to have access to the 
same private variables, and have ensured that those variables won't be accessed at the 
same time. That is the end goal of my multithreading*/

class test_obj {
public:
    test_obj();
    void run_stuff(int); //the method I want to run on two different threads using the same private variables
private:
    int count;
    void switch_gate1();//switches the value of gate 1
    void switch_gate2();
    bool test_gate1(int); //checks to see if gate 1 equals thread id
    bool test_gate2(int);
    bool gate1, gate2; //can only be accessed under a locked mutex
    pthread_mutex_t lock1, lock2;
};

/*This structure is what I pass to pthread_create*/
struct thread_args { //arguements passed to a thread when it is created
    thread_args() {a = new test_obj;}; //constructor: create new test_obj instance
    test_obj *a; //pointer to a test_obj instance, I think both threads receive a pointer to the same instance
    int t_id; //ID of thread being created
};

class thread_helper { //managing function to create threads and call run_stuff method
public:
    thread_helper() {args = new thread_args;};
    void my_method(); //called from main, creates threads and runs them
private:
    thread_args *args; //pointer to a thread_args obj
    static void* execute(void *ptr); //method to be run by created threads
    pthread_t m_thread1, m_thread2; //the two threads
};

int main() {
    thread_helper c; 
    c.my_method();
    return 0;
}

test_obj::test_obj() {
    count = 0; //not important right now, test variable
    gate1 = 0; //thread 0 gets first access
    gate2 = 0; //thread 0 gets first access
}

void thread_helper::my_method() {
    int error_code;
    thread_args *a, *b;
    *a = *b = *args;
    a->t_id = 0;
    b->t_id = 1;
    error_code = pthread_create(&m_thread1, NULL, &thread_helper::execute, (void*)a); //create thread 0 to run execute method
    assert(0 == error_code); //check for success
    error_code = pthread_create(&m_thread2, NULL, &thread_helper::execute, (void*)b);
    assert(0 == error_code);
    error_code = pthread_join(m_thread1, NULL);//wait for thread 0
    assert(0 == error_code);
    error_code = pthread_join(m_thread2, NULL); //wait for thread 1
    assert(0 == error_code);
}

void* thread_helper::execute(void *ptr) {
    thread_args *b = (thread_args*)ptr;//recast ptr back into thread_args type
    int t_id = b->t_id;//save thread id
    b->a->run_stuff(t_id);//access test_obj object from thread_args (should be same object for both threads) and run method
    return NULL;
}

void test_obj::run_stuff(int t_id) {
    for(int i = 0; i < 2; i++) { //run twice (give a chance for threads to flip flop)
    //-----Part 1
    while(!test_gate1(t_id)){//while not allowed to proceed
        Sleep(500);//sleep
    }
    printf("thread %d reporting in\n", t_id);//thread has gained access to part 1, print id
    switch_gate1();//allow opposite thread in
    //-----Part 2
    while(!test_gate2(t_id)){//wait for access to part 2
        Sleep(500);
    }
    //count++; //just a dummy place for now, will be used later to check access
    switch_gate2();//allow opposite thread in
    }
}

bool test_obj::test_gate1(int t_id) {//returns true if id of calling thread matches value of gate 1
//a return value of true means a thread is allowed to proceed, false otherwise
    pthread_mutex_lock(&lock1);**//secure access to gate THIS IS WHAT ERRORS OUT**
    if(t_id == gate1){//check gate
        pthread_mutex_unlock(&lock1);//release gate
        return true;//return
    }
    else {
        pthread_mutex_unlock(&lock1);
        return false;
    }
}

bool test_obj::test_gate2(int t_id) {
    pthread_mutex_lock(&lock2);
    if(t_id == gate2){
        pthread_mutex_unlock(&lock2);
        return true;
    }
    else {
        pthread_mutex_unlock(&lock2);
        return false;
    }
}

/*Switch gate functions are designed to obtain access to the boolean gate (prevent the opposing thread from checking the gate by means of mutex), then switch the value of the boolean gate and release the gate for the other thread to check.*/
void test_obj::switch_gate1() {
    pthread_mutex_lock(&lock1);//secure access to gate
    gate1 = !gate1; //flip gate
    pthread_mutex_unlock(&lock1); //release gate
}

void test_obj::switch_gate2() {
    pthread_mutex_lock(&lock2);
    gate2 = !gate2;
    pthread_mutex_unlock(&lock2);
}

对格式问题感到抱歉。任何人都知道为什么该锁会出现访问冲突错误?我试过把它放在任何地方。私人的、公共的,甚至是全球性的作为最后的手段。他们都给出了同样的错误。提前致谢。

编辑:修复了将我的 thread_args 变量传递给 pthreads_create 的错误。之后现在可以按预期工作并进行初始化/销毁修复。

【问题讨论】:

  • 你初始化你的互斥锁了吗?
  • lock1 和 lock2 在哪里定义/初始化?
  • 已修复:抱歉,在全局尝试后忘记将 lock1 和 lock2 添加回成员变量中。
  • Windows 没有本地 pthreads 库;你在用 Cygwin 吗?
  • Windows 没有原生的,但可以下载。提供 32 位和 64 位版本

标签: c++ multithreading pthreads mutex access-violation


【解决方案1】:

您似乎没有初始化您的互斥锁。我看不到您在哪里声明了互斥锁。

test_obj 中声明变量:

pthread_mutex_t lock1;
pthread_mutex_t lock2;

将此添加到您的 test_obj 构造函数中:

test_obj::test_obj() {
    ...
    lock1 = PTHREAD_MUTEX_INITIALIZER;
    lock2 = PTHREAD_MUTEX_INITIALIZER;
}

将此添加到 test_obj 析构函数:

test_obj::~test_obj() {
    pthread_mutex_destroy(&lock1);
    pthread_mutex_destroy(&lock2);
}

【讨论】:

  • 另外,应该添加一个 dtor,在它们上调用 pthread_mutex_destroy()
  • @Michael Burr - 你是正确的迈克尔!我添加了析构函数所需的代码。
  • 这就是问题所在!感谢您的协助。通常是 pthreads、mutex 和处理器多线程的新手。现在进入下一个错误!
  • 您应该在运行时调用pthread_mutex_init 来初始化pthread_mutex_tPTHREAD_MUTEX_INITIALIZER 仅用于在声明对象时对其进行初始化,例如pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER(特别是文件范围内的全局对象)。它恰好可以工作是幸运的,但它可能无法在其他平台上编译。
  • 感谢您的提醒,有机会我会改变的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-28
  • 2020-02-24
  • 1970-01-01
  • 1970-01-01
  • 2015-06-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多