Windows下的多线程

本文详细探讨了Windows环境下实现多线程同步与互斥的方法,包括关键段、互斥量、事件和信号量。通过实例分析,比较了各种机制在进程互斥中的应用,同时提到了软件解决方法和硬件原子操作在多线程控制中的作用。
摘要由CSDN通过智能技术生成

Windows下多线程的同步与互斥

critical section

#include <stdio.h>
#include <process.h>
#include <windows.h>

// Usage
// EnterCriticalSection(CRITICAL_SECTION)
// ...//do some thing
// LeaveCriticalSection(CRITICAL_SECTION)

long global;
unsigned int __stdcall ThreadFunction(void *handle);
const int THREAD_NUM = 10;  //if the number is more than 100,there will be a question
// definition of critical section
CRITICAL_SECTION g_csThreadCode;

int main()
{
    // initialize critical section
    InitializeCriticalSection(&g_csThreadCode);

    HANDLE handle[THREAD_NUM];
    global = 0;
    int i = 0;
    while (i < THREAD_NUM) 
    {
        handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunction, &i, 0, NULL);
        ++i;  
    }
    WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); //wait for all threads to finish the task
    DeleteCriticalSection(&g_csThreadCode);

    return 0;
}

unsigned int __stdcall ThreadFunction(void *handle)
{
    EnterCriticalSection(&g_csThreadCode);  // enter critical section
    global++;
    Sleep(0);                               //重新发起一次CPU竞争
    printf("global variable is %d\n",global);
    LeaveCriticalSection(&g_csThreadCode);
    return 0;
}

这个例子当线程数设置为150时,我的主机就无法正常全部打印了

mutex

// 互斥量Mutex:
// Usage
// WaitForSingleObject(hMutex,…);  
// ...//do something  
// ReleaseMutex(hMutex);  

#include <stdio.h>
#include <process.h>
#include <windows.h>

long global;
unsigned int __stdcall ThreadFunction(void *handle);
const int THREAD_NUM = 10;
// 互斥量
HANDLE hmutex; 

int main()
{
    // 初始化互斥量,第二个参数为TRUE表示互斥量为创建进程所有
    hmutex = CreateMutex(NULL, FALSE, NULL);

    HANDLE handle[THREAD_NUM];
    global = 0;
    int i = 0;
    while (i < THREAD_NUM) 
    {
        handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunction, &i, 0, NULL);
        i++;
    }
    WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
    // 销毁互斥量
    CloseHandle(hmutex);
    return 0;
}

unsigned int __stdcall ThreadFunction(void *handle)
{
    WaitForSingleObject(hmutex, INFINITE);  // 等待互斥量被触发
    global++;
    Sleep(0);
    printf("global variable is %d\n", global);
    ReleaseMutex(hmutex);   // 触发互斥量
    return 0;
}

互斥量和关键段的区别互斥量可以设置等待时间

event

// Usage
// SetEvent(hEvent);
// WaitForSingleObject(hEvent,…);
// 等待其他进程的setevent,然后执行操作

#include <stdio.h>  
#include <process.h>  
#include <windows.h>  
long global;  
unsigned int __stdcall ThreadFunction(void *handle);  
const int THREAD_NUM = 10;  
//事件
HANDLE hevent;
int main()  
{  
    //初始化事件初
    hevent = CreateEvent(NULL, FALSE, FALSE, NULL);
    HANDLE  handle[THREAD_NUM];   
    global = 0;  
    int i = 0;  
    SetEvent(hevent);  //如果这一行注释,则事件没有触发,所有线程等待
    while (i < THREAD_NUM)   
    {  
        handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunction, &i, 0, NULL);  
        i++;  
    }  
    WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);  
    //销毁事件
    CloseHandle(hevent);  
    return 0;  
}  
unsigned int __stdcall ThreadFunction(void *handle)  
{
    WaitForSingleObject(hevent,INFINITE);
    global++;  
    Sleep(0);
    printf("global variable is %d\n",global);   
    SetEvent(hevent); //触发事件 
    return 0;  
}  

事件更适合一个线程像另一个线程发送通知消息

semaphore

// WaitForSingleObject(hsemaphore,INFINITE);
// ...//do something
// ReleaseSemaphore(hsemaphore, 1, NULL);

#include <stdio.h>
#include <process.h>
#include <windows.h>

long global;
unsigned int __stdcall ThreadFunction(void *handle);
const int THREAD_NUM = 10;
// 信号量
HANDLE hsemaphore;

int main()
{
    // 初始化信号量和关键段
    hsemaphore = CreateSemaphore(NULL, 0, 1, NULL); // 当前0个资源,最大允许1个同时访问
    ReleaseSemaphore(hsemaphore, 1, NULL);  // 信号量++,多出一个资源,如果注释掉,所有线程等待
    HANDLE handle[THREAD_NUM];
    global = 0;
    int i = 0;
    while (i < THREAD_NUM) 
    {
        handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFunction, &i, 0, NULL);
        ++i;
    }
    WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);

    // 销毁信号量
    CloseHandle(hsemaphore);
    return 0;
}

unsigned int __stdcall ThreadFunction(void *handle)
{
    WaitForSingleObject(hsemaphore,INFINITE);
    global++;
    Sleep(0);
    printf("global variable is %d\n",global);
    ReleaseSemaphore(hsemaphore, 1, NULL);  // 信号量++
    return 0;
}

semaphore针对资源而言,对于一个区间允许有多个线程访问

以上几种方法的对比

critical sectionmutexeventsemaphore
非内核内核内核内核
只能同步单个进程的线程  属于PV操作
可以由软件层面忙等来实现互斥量是可以命名的,也就是说它可以跨越进程使用主要用于消息通知等允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目

进程互斥的软件解决方法

  • Use two shared data items
int turn; //指示该谁进入临界区  
bool flag[]; //指示进程是否准备好进入临界区
  • code for enter critical section
flag[i] = TRUE;
turn = j;
while(flag[j]&&turn==j);
  • code for exit critical section
flag[j]=FALSE;

其他基于硬件的原子操作

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值