2012-10-31 67 views
3

我正在編寫一個讀取和處理大量數據的程序。爲了加速這個過程,我使用C++的Pthreads庫實現了多線程讀/處理。然而,當我在我的互斥量上調用pthread_mutex_lock(& lock1)時,我的程序錯誤超出了lock1地址上的「訪問衝突讀取位置」錯誤。我需要在一個類的方法上運行這些線程,這需要在pthread庫的限制範圍內進行一些操作,並且這是我犯了錯誤的那種操縱。以下是我的代碼的縮寫版本,對於tl; dr。抱歉。儘可能地縮短它,而不會遺漏任何對多線程至關重要的部分:Pthread_mutex_lock返回訪問錯誤

#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的錯誤。在此之後按預期工作,並初始化/銷燬修復程序。

+0

你初始化互斥? – Starkey

+0

鎖定1和鎖定2在哪裏定義/初始化? – sehe

+0

修正:對不起,忘了在全局嘗試後將lock1和lock2添加回成員變量。 – LiamK

回答

5

你似乎沒有初始化你的互斥鎖。我看不到你有哪些互斥體的聲明。

聲明變量在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); 
} 
+1

另外,應該有一個dtor添加,他們調用'pthread_mutex_destroy()'。 –

+0

@邁克爾伯爾 - 你是對的邁克爾!我添加了析構函數所需的代碼。 – Starkey

+0

這就是問題所在!感謝您的幫助。一般來說,pthreads,互斥體和處理器多線程是新的。現在到下一個錯誤! – LiamK

相關問題