如何使用windows.h锁定和解锁互斥锁

时间:2020-07-20 18:11:53

标签: c++ winapi

好,所以我试图学习多线程的基础知识,在这种情况下,我试图使用互斥锁来控制对共享缓冲区的访问。我介绍了所有延迟和while循环,以扩大问题,即互斥锁似乎未锁定,或者我的第二个线程实际上没有在等待互斥锁对象被解锁。如果有人可以指出我正在犯的错误,我将最好地遵循msdn语法,将不胜感激。下面是代码,然后是输出。如果看不到图片,则将数据打印为1 1 1 1几次迭代,然后最终打印正确的值,这表明它根本不等待互斥体。

#include <thread>
#include <fstream>
#include <Windows.h>

struct data{
        uint8_t accel;
        uint8_t check;
        uint8_t testint;
        uint8_t value;
};

char buff[1000];
bool writef = false;
HANDLE mymutex;


void thread1() {
    
using namespace std::literals::chrono_literals;
    OpenMutexW(MUTEX_ALL_ACCESS, TRUE, TEXT("firstmutex"));
    if (mymutex == NULL) printf("mutex failed here: %d \n", GetLastError());

    std::cout << "started thread id = " << std::this_thread::get_id() << std::endl;
    //create instance of data and assign the actual data    
    data data1;
    data* ptdata = &data1; //crteate a pointer to the struct object
    printf("pointers 2 data1 \t %p \n ", ptdata);//DEBUG 
    data1.accel = 45;
    data1.check = 34;
    data1.testint = 2;
    data1.value = 19;
    printf("pointer 2 the buffer \t %p \n", buff);//DEBUG AID

    //lock the buff for thread 1 access
    memcpy(buff, ptdata, 4); //copy the content fo data1 into the buffer 
    writef = true;
    for(int i = 0 ; i < 50000000; i++){} //delay
    ReleaseMutex(mymutex);

}


void thread2() {
    using namespace std::literals::chrono_literals;
    bool read = false;
    std::cout << "started thread id = " << std::this_thread::get_id() << std::endl;
    data data2;
    data* dataout = &data2;
    memset(dataout, 0, sizeof(data2));
    printf("p 2 dataout \t %p \n ", dataout);
    while (!read) {
        int c = 0;
        //we need to lock the buff while performing this operation
        printf("waiting %d : \n", c);
        WaitForSingleObject(mymutex, INFINITE); // says wait for the mutext to be released indefinantly
        memcpy(dataout, buff, sizeof(buff + 1)); // copy the data in the buffer to data2 structure.

        printf("this should be the data from the source : ");
        printf(" %d \t %d \t %d \t %d \n", dataout->accel, dataout->check, dataout->testint, dataout->value); //print out the original data
        ReleaseMutex(mymutex); // releases the mutex after a full copy and print occurs 
        c++;
        if (dataout->accel > 1) read = true;
    } 
}

int main() {

    std::cout << sizeof(int);
    std::cout << sizeof(char) << std::endl;

    mymutex = CreateMutexW(NULL, FALSE, TEXT("firstmutex")); // parameters 1= security level 2= ownership 3= object name
    if (mymutex == NULL)printf("mutex creation failed: %d \n", GetLastError());

    memset(buff, 1, sizeof(buff)); //zero out the buffer to initialize and reset

    std::thread datasource(thread1);

    for (int i = 0; i < 20000; i++); // this is just a delay 
    std::thread dataoutput(thread2);
    datasource.join();
    dataoutput.join();
    std::cin.get();

    return 0;

}

enter image description here

1 个答案:

答案 0 :(得分:0)

好吧,这是对上面的代码进行了修改,以简单地测试和学习一种使用互斥量来控制线程对数据的使用的方法。我也喜欢尽可能地坚持使用标准库,以实现跨平台功能以及对特殊头文件的依赖。因此,我很高兴先前发布的评论使我朝着这个方向发展。无论如何,这段代码会创建一个互斥体并保护缓冲区,因为第二个线程试图在第一个线程将数据复制到缓冲区之前读取并输出该缓冲区。互斥锁成功地阻止了这种情况,线程2仅在获得对互斥锁的控制后才输出缓冲区。

#include <thread>
#include <fstream>
#include <Windows.h>
#include <mutex>


struct data{
        uint8_t accel;
        uint8_t check;
        uint8_t testint;
        uint8_t value;
};

char buff[500];
bool writef = false;
std::mutex buff_mutex; //create the mutex around the buffer

void thread1() {
    
    buff_mutex.lock();// lock the buffer variable
    using namespace std::literals::chrono_literals;

    std::cout << "started thread id = " << std::this_thread::get_id() << std::endl;
    //create instance of data and assign the actual data    
    data data1;
    data* ptdata = &data1; //crteate a pointer to the struct object
    printf("pointers 2 data1 \t %p \n ", ptdata);//DEBUG 
    data1.accel = 45;
    data1.check = 34;
    data1.testint = 2;
    data1.value = 19;
    printf("pointer 2 the buffer \t %p \n",buff);//DEBUG AID

    //lock the buff for thread 1 access
    memcpy(buff, ptdata, 4); //copy the content fo data1 into the buffer 
    writef = true;
    for(int i = 0 ; i < 50000000; i++){} //delay
    buff_mutex.unlock(); // unlock the buffer for the second thread to acces it after the write op has been completed
    

}


void thread2() {
    using namespace std::literals::chrono_literals;
    bool read = false;
    std::cout << "started thread id = " << std::this_thread::get_id() << std::endl;
    data data2;
    data* dataout = &data2;
    memset(dataout, 0, sizeof(data2));
    printf("p 2 dataout \t %p \n ", dataout);
    while (!read) {
        int c = 0;
        //we need to lock the buff while performing this operation
        if (buff_mutex.try_lock()) { //try to unlock the mutex the return value is a bool true= success false= could not lock the mutex
            memcpy(dataout, buff, sizeof(buff + 1)); // copy the data in the buffer to data2 structure.
            printf("this should be the data from the source : ");
            printf(" %d \t %d \t %d \t %d \n", dataout->accel, dataout->check, dataout->testint, dataout->value); //print out the original data 
            read = true;
            buff_mutex.unlock();
        }
        else {
            printf("failed attempt %d \n", c);
            c++;
        }
        
    } 
}

int main() {

    std::cout << sizeof(int);
    std::cout << sizeof(char) << std::endl;

    memset(buff, 1, sizeof(buff)); //zero out the buffer to initialize and reset

    std::thread datasource(thread1);

    for (int i = 0; i < 20000; i++); // this is just a delay 
    std::thread dataoutput(thread2);
    datasource.join();
    dataoutput.join();
    std::cin.get();

    return 0;

} ```
相关问题