多线程同步队列实现

多线程同步队列


0x01 程序结构

将多线程同步队列实现为类,对外提供以下接口:

  • get()
  • put()

类内部维护三个句柄用于同步:

  • full信号量表示是否可读
  • empty信号量表示是否可写
  • buffer_mutex互斥对象用于同步对缓冲区的操作

队列中保存指针,这样可实现保存多种类型的对象。

0x02 代码

multithreadedqueue.h


#ifndef ____MULTITHREADEDQUEUE____H____
#define ____MULTITHREADEDQUEUE____H____

#include <windows.h>
typedef unsigned long * pointer32;
class queue
{
    pointer32 * buffer;
    int first;
    int last;
    int buffer_len;

    HANDLE full;
    HANDLE empty;
    HANDLE buffer_mutex;
public:
    queue(int len = 5);
    void put(pointer32 element);
    pointer32 get();
    ~queue();
};

#endif

multithreadedqueue.cpp


#include "multithreadedqueue.h"
#include <Windows.h>

#define TEST

#ifdef TEST
#include <stdio.h>
#endif

queue::queue(int len)
{
    buffer_len = len;
    buffer = new pointer32 [buffer_len];
    first = 0;
    last = 0;

    full = CreateSemaphore(NULL, 0, buffer_len-1, NULL);
    empty = CreateSemaphore(NULL, buffer_len-1, buffer_len-1, NULL);
    buffer_mutex = CreateMutex(NULL, FALSE, NULL);
}

pointer32 queue::get()
{
    pointer32 ret;
    WaitForSingleObject(full, INFINITE);
    WaitForSingleObject(buffer_mutex, INFINITE);

    ret = *(buffer + first);
    first = (first + 1) % buffer_len;

#ifdef TEST
    printf("consumer no.%d: value is %d, addr is 0x%08u\n", GetCurrentThreadId(), *(int*)ret, ret);
    Sleep(100);
#endif // TEST

    ReleaseMutex(buffer_mutex);
    ReleaseSemaphore(empty, 1, NULL);
    return ret;
}

void queue::put(pointer32 element)
{
    WaitForSingleObject(empty, INFINITE);
    WaitForSingleObject(buffer_mutex, INFINITE);

    *(buffer + last) = element;
    last = (last + 1) % buffer_len;

#ifdef TEST
    printf("producer no.%d: value is %d, addr is 0x%08u\n", GetCurrentThreadId(), *(int*)element, element);
    Sleep(100);
#endif // TEST

    ReleaseMutex(buffer_mutex);
    ReleaseSemaphore(full, 1, NULL);
}

queue::~queue()
{
    CloseHandle(full);
    CloseHandle(empty);
    CloseHandle(buffer_mutex);
    delete [] buffer;
}

0x03 测试

test.cpp

#include <windows.h>
#include "multithreadedqueue.h"
#include <stdio.h>

queue q;

DWORD WINAPI Producer(PVOID pvParam)
{
    while (1)
    {
        q.put((pointer32)new int(rand()));
    }

    return 0;
}

DWORD WINAPI Consumer(PVOID pvParam)
{
    pointer32 value;

    while (1)
    {
        value = q.get();
        delete value;
    }
    return 0;
}

int main()
{
    HANDLE hThread;
    DWORD thread_id;
    DWORD producer_count, consumer_count, exec_time;
    printf("producer_count, consumer_count, exec_time:\n");
    scanf("%u %u %u", &producer_count, &consumer_count, &exec_time);
    while (producer_count--)
    {
        hThread = CreateThread(NULL, 0, Producer, NULL, 0, &thread_id);
        CloseHandle(hThread);
    }
    while (consumer_count--)
    {
        hThread = CreateThread(NULL, 0, Consumer, NULL, 0, &thread_id);
        CloseHandle(hThread);
    }

    Sleep(exec_time);

    return 0;
}

测试用例1: 1生产者,1消费者,运行1秒

测试用例2: 1生产者,4消费者,运行3秒

测试用例3: 4生产者,1消费者,运行3秒

测试用例4: 4生产者,4消费者,运行5秒

输出中的value为生成对象的值,addr为地址。值一样时用地址区分存入 队列的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值