上一篇博文:
https://blog.csdn.net/qq78442761/article/details/81276366
这里有一点:
CRITICAL_SECTION
此玩意,类似于互斥锁,是Windows平台提供的。
程序运行截图如下:
源码如下:
DeadLock.h
#pragma once
#include <windows.h>
#include <iostream>
using namespace std;
#define PRODUCERCNT 1 //生产者线程数量
#define CONSUMERCNT 1 //消费者线程数量
#define TOTALCNT PRODUCERCNT+CONSUMERCNT
class CDeadLock
{
public:
CDeadLock();
~CDeadLock();
void CreateThread();
void ToggleStatus();
private:
HANDLE hConsole; //控制台句柄-改变控制台颜色输出
bool m_bRunning; //通知线程需要关闭
int m_buffer; //关键数据-临界资源
HANDLE threads[TOTALCNT]; //保存所有线程句柄
static DWORD WINAPI producer(LPARAM lParam); //生产者线程函数
static DWORD WINAPI consumer(LPARAM lParam); //消费者线程函数
//生产和消费动作
void produce();
void consume();
//Windows中提供了关键段,来协调
CRITICAL_SECTION m_cs;
};
DeadLock.cpp
#include "DeadLock.h"
CDeadLock::CDeadLock()
{
hConsole = INVALID_HANDLE_VALUE;
m_bRunning = false;
m_buffer = 0;
for (int i = 0; i < TOTALCNT; i++) {
threads[i] = INVALID_HANDLE_VALUE;
}
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTitle(L"死锁");
InitializeCriticalSection(&m_cs);
}
CDeadLock::~CDeadLock()
{
CloseHandle(hConsole);
for (int i = 0; i < TOTALCNT; i++) {
if (threads[i] != INVALID_HANDLE_VALUE) {
CloseHandle(threads[i]);
}
}
DeleteCriticalSection(&m_cs);
}
void CDeadLock::CreateThread()
{
int i = 0;
m_bRunning = true;
for (; i < PRODUCERCNT; i++) {
threads[i] = ::CreateThread(0, 0, (LPTHREAD_START_ROUTINE)producer, this, 0, 0);
}
for (i = 0; i < CONSUMERCNT; i++) {
threads[i] = ::CreateThread(0, 0, (LPTHREAD_START_ROUTINE)consumer, this, 0, 0);
}
}
void CDeadLock::ToggleStatus()
{
m_bRunning = !m_bRunning;
}
//生产者线程
DWORD WINAPI CDeadLock::producer(LPARAM lParam)
{
CDeadLock *pThis = (CDeadLock*)lParam;
cout << "producer threadID:" << GetCurrentThreadId() << endl;
while (pThis->m_bRunning) {
EnterCriticalSection(&pThis->m_cs);
SetConsoleTextAttribute(pThis->hConsole, FOREGROUND_RED);
pThis->produce();
LeaveCriticalSection(&pThis->m_cs);
}
return 0;
}
//消费者线程
DWORD WINAPI CDeadLock::consumer(LPARAM lParam)
{
CDeadLock *pThis = (CDeadLock*)lParam;
cout << "consumer threadID:" << GetCurrentThreadId() << endl;
while (pThis->m_bRunning) {
Sleep(10);
EnterCriticalSection(&pThis->m_cs);
SetConsoleTextAttribute(pThis->hConsole, FOREGROUND_GREEN);
pThis->consume();
LeaveCriticalSection(&pThis->m_cs);
}
return 0;
}
void CDeadLock::produce()
{
if (m_buffer > 200) {
return;
}
//m_buffer++;
__asm {
mov eax, dword ptr[this] //取this指针
mov ecx, dword ptr[eax + 8] //取m_buffer的值,放在ecx寄存器里面
//有可能执行到这一步,发送时间片到期的状态... 如果是10,那么这个10已经到了ecx寄存器里面,
//这时候,消费者开始消耗了,消费者消耗完后应该是9,
//但是,这个时候生产者的时间片又到了,此时把寄存器++,变成了11,这样就有问题了!!!
add ecx, 1 //ECX++
mov edx, dword ptr[this] //取this指针
//此处可以直接这么优化 mov dword prt[eax+8],ecx
mov dword ptr[edx + 8], ecx //再放回去
}
printf("生产 - %d\n", m_buffer);
}
void CDeadLock::consume()
{
int data = m_buffer--;
if (data) {
printf("消费 - %d\n", data);
}
}
main.cpp
#include "DeadLock.h"
#include <conio.h>
void main() {
cout << "main called!\n";
CDeadLock deadLock;
deadLock.CreateThread(); //注意,如果CreateThread两次,那么以前的线程就会被抛弃掉
cout << "press any key to exit ... \n";
while (true) {
char cmd = _getch();
if (cmd == 'q') {
break;
}
else if (cmd == 'n') {
deadLock.ToggleStatus();
}
}
}