VC windows api 多线程---互斥量、信号量、临界值

以下摘自 http://blog.sina.com.cn/s/blog_5040a4e90100gntv.html

互斥量的用途和临界区很像。它与临界区的差别在于可以跨线程使用,可以用来同步进行多个线程间的数据访问,但是是以牺牲速度为代价的。只有临界区是非核心对象,那么互斥量就是一个核心对象了。核心对象的特点是有所谓的引用计数。所著一个未被拥有的互斥量,比锁住一个未被拥有的临界区需要花费几乎100倍的时间(数据引用自《Visual C++ 6.0编程学习捷径》)。

 Win32 API有一套互斥量的支持函数:


创建互斥量.
 * @param lpMutexAttributes 指定安全属性,NULL表示使用默认的属性.
 * @param bInitialOwner 指出创建互斥量的线程是否要成为该互斥量的最初拥有.
 * TRUE表示拥有,因此互斥量将处于无信号状态.
 * FALSE表示互斥量不被任何现成拥有,因此处于有信号状态.
 * @param lpName为NULL或标识该互斥量的一个字符串的地址,任何进程或线程都可以根据此名称使用该互斥量.
 * 当应用程序调用CreateMutex()函数时,系统分配一个互斥量的核心对象,把它的名字设为lpName所致的字符串.
 * 该名字在进程间共享互斥量。CreateMutex()返回一个标识新互斥量对象的进程相关的句柄.
HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName);

 

打开互斥量.
 * @param dwDesiredAccess 可设置为MUTEX_ALL_ACCESS或SYNCHRONIZE.
 * @param bInheritHandle 指出该进程创建的子进程能否继承该互斥量.
 * @param lpName 指定互斥量的名字.
HANDLE OpenMutex(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName);

 

释放互斥量.
 * @param hMutex 要释放的互斥量的句柄.
BOOL ReleaseMutex(HANDLE hMutex);

 

 

 

-------------------------------------------
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <stdlib.h>

#define  threadnum 10

typedef struct THREADDATA
{
   int id;
   char name[10];
   int sleep;
}THREADDATA;


HANDLE handleMutex;

char * str;

DWORD WINAPI ThreadProc( LPVOID lpParam )
{
   THREADDATA *data=(THREADDATA *)lpParam;
   //WaitForSingleObject(handleMutex,INFINITE);
   for(int i=0;i<10;i++)
   {
    WaitForSingleObject(handleMutex,INFINITE);
    printf("thread%d:%d\n",data->id,i);
    ReleaseMutex(handleMutex);
    Sleep(data->sleep);

   }
 //  ReleaseMutex(handleMutex);
   return 0;
}

int main(int argc, char* argv[])
{
   str=(char*)malloc(30);
   THREADDATA  pData[threadnum];
   DWORD dwThreadId[threadnum];
   HANDLE hThread[threadnum]; 

   handleMutex= CreateMutex(NULL,false,NULL);

   for(int i=0;i<threadnum;i++)
   {
     pData[i].id=i;
     sprintf(pData[i].name,"yuguoqing");
     pData[i].sleep=i*10;
     hThread[i] = CreateThread(NULL,0,ThreadProc, pData+i, 0,  dwThreadId+i);
   }

    WaitForMultipleObjects(threadnum, hThread, TRUE, INFINITE);

    return 0;
} 

VC windows api 多线程---信号量

 

信号量(Semaphore)和互斥量一样,属于内核对象。它自动执行可用资源查询的测试,如果有可用资源,则可用资源的计数减少,从而避免其它线程请求资源。当该线程释放该资源后,可用资源计数增加,则操作系统允许另一个线程请求资源。

信号量与临界区和互斥量的不同在于,它不能被认为属于某个线程。也就是说,一个线程可以等待信号量对象(减少它的资源计数),而另一个线程释放该对象(增加它的资源计数)。

Win32 API提供了几个函数用于支持信号量。使用Win32 API产生一个信号量,必须首先调用CreateSemaphore()函数,该函数描述如下:

创建一个信号量
 
*@param lpSemaphoreAttributes 指定安全属性,如果是NULL就表示使用默认属性。
 
*@param lInitialCount 用于指定该信号量的初始资源计数,必须大于或等于0,并且小于或等于lMaximumCount。
 
*@param lMaximumCount 指定信号量的最大资源计数。
 
*@param lpName 是赋给信号量的字符串名字。
HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName);     

 

你可以根据信号量的字符串名字得到该信号量的句柄: 
 
*@param dwDesiredAccess 访问方式,同互斥量参数。
 
*@param bInheritHandle 继承特性,同互斥量参数。
 
*@param lpName 信号量名字。
HANDLE OpenSemaphore(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName);     

 

释放信号量函数:
 
*@param hSemaphore 信号量的句柄。
 
*@param lReleaseCount指信号量现值的增额,该值必须大于0。
 
*@param lpPreviousCount 传回信号量原来的计数,可以为NULL。
BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount);
      
释放信号量函数与释放互斥量函数形式相同,但不同之处在于:
一、任意线程可以在任意时刻调用此函数,因为信号量对象不为某个线程拥有。
二、ReleaseSemaphore()函数可以用大于1的大小来增加信号量的资源计数。


---------------------------------------

#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <stdlib.h>

#define  threadnum 10

typedef struct THREADDATA
{
   int id;
   char name[10];
   int sleep;
}THREADDATA;


HANDLE handleSemaphore;
char * str;

DWORD WINAPI ThreadProc( LPVOID lpParam )
{
   THREADDATA *data=(THREADDATA *)lpParam;
 
   WaitForSingleObject(handleSemaphore,INFINITE);
   for(int i=0;i<10;i++)
   {
 // WaitForSingleObject(handleSemaphore,INFINITE);
   printf("thread%d:%d\n",data->id,i);
 // ReleaseSemaphore(handleSemaphore,1,NULL);
   Sleep(data->sleep);

   }
   ReleaseSemaphore(handleSemaphore,1,NULL);
   return 0;
}

int main(int argc, char* argv[])
{
   str=(char*)malloc(30);
   THREADDATA  pData[threadnum];
   DWORD dwThreadId[threadnum];
   HANDLE hThread[threadnum];

   handleSemaphore=CreateSemaphore(NULL,1, 2,"thread");

   for(int i=0;i<threadnum;i++)
   {
     pData[i].id=i;
     sprintf(pData[i].name,"yuguoqing");
     pData[i].sleep=i*10;
     hThread[i] = CreateThread(NULL,0,ThreadProc, pData+i, 0,  dwThreadId+i);
   }

    WaitForMultipleObjects(threadnum, hThread, TRUE, INFINITE);
    return 0;
}

VC windows api 多线程---临界区



在有几个线程并行运行的环境中,同步不同线程的活动是非常重要的。一般说来,一个线程使自己与另一个线程同步的方法是让自己睡眠。但线程睡眠时,操作系统不再为它调度CPU时间,因此它停止了执行。不过,就在它睡眠之前,它告诉系统要让它恢复执行,必须有什么“特殊事件”发生。操作系统记住该线程的请求,监视着“特殊事件”是否发生以及何时发生。当它发生时,线程才又能够加入到CPU时间等待队列中。一旦被预订,线程就能继续执行了。此时,线程就将它的执行与时间的发生取得了同步。

    Windows操作系统提供了设定“特殊事件”的方法,就是使用同步对象。我将在今后学习常用的四种同步对象:临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、事件(Event)。

    上述四种同步对象,除了临界区外都是内核对象。临界区不被操作系统的低级部件管理,而且不能使用句柄来操纵,是最易于使用和理解的同步对象。

    当多个线程共享对同一数据的访问时,线程之间可能会有干扰。一个临界区对象保护一段代码不被多于一个线程访问。在所有的同步对象中,临界区是最容易使用的,但是,一个临界区对一个进程或DLL是有限的,不能被其他进程共享,只能用于同步单个进程中的线程。临界区不是Windows核心对象,它和核心对象不同,存在于进程的内存空间中。

    Win32 API提供了几个临界区函数:

void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);

    CRITICAL_SECTION类型的变量用来扮演红绿灯的角色,让同一个时间内只有一个线程进入临界区。该临界区变量的声明必须是全局的,这样不同的线程就能访问它。操纵临界区的Win32函数初始化和维护该结构中的所有成员,不要自己去访问和修改任何成员。

    使用临界区之前,必须调用InitializeCriticalSection()函数来初始化临界区。而通过调用EnterCriticalSection()函数来取得一个临界区的所有权。然后通过LeaveCriticalSection()函数来释放所有权。临界区通过一个线程取得所有权来显示它已经进入代码临界区的方法进行工作,如果其他线程调用EnterCriticalSection()并引用同一临界区,它会被阻塞,直到第一个线程调用LeaveCriticalSection()函数。最后,可以调用DeleteCriticalSection()函数来释放用户初始化临界区时分配的系统资源。

   
    在MFC中封装了CCriticalSection类作为临界区对象,在构造函数中自动调用InitialCriticalSection()函数,在析构函数中自动调用LeaveCriticalSection()函数,用Lock()和Unlock()对应取得所有权和释放所有权。

 

----------------------------------------------

#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <stdlib.h>

#define  threadnum 10

typedef struct THREADDATA
{
   int id;
   char name[10];
   int sleep;
}THREADDATA;

CRITICAL_SECTION sec1;

char * str;

DWORD WINAPI ThreadProc( LPVOID lpParam )
{
   THREADDATA *data=(THREADDATA *)lpParam;
   printf("%d\n%s\n",data->id,data->name);
   EnterCriticalSection(&sec1);
   for(int i=0;i<10;i++)
   {
 //  EnterCriticalSection(&sec1);
   printf("thread%d:%d\n",data->id,i);
 //  LeaveCriticalSection(&sec1);
   Sleep(data->sleep);

   }
   LeaveCriticalSection(&sec1);

   return 0;
}

int main(int argc, char* argv[])
{
   str=(char*)malloc(30);
   THREADDATA  pData[threadnum];
   DWORD dwThreadId[threadnum];
   HANDLE hThread[threadnum];

   InitializeCriticalSection(&sec1);
 
   for(int i=0;i<threadnum;i++)
   {
     pData[i].id=i;
     sprintf(pData[i].name,"yuguoqing");
     pData[i].sleep=i*10;
     hThread[i] = CreateThread(NULL,0,ThreadProc, pData+i, 0,  dwThreadId+i);
   }

    WaitForMultipleObjects(threadnum, hThread, TRUE, INFINITE);

 return 0;
}



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
丢失api-ms-win-core-com-l1-1-0.dll文件的问题可以通过以下几种方法来解决: 方法一:手动下载并安装dll文件 1. 从可信赖的网站下载api-ms-win-core-com-l1-1-0.dll文件,确保下载的文件版本与你系统的要求匹配。 2. 将下载的dll文件复制到你要运行的软件或游戏的安装目录中,通常是在C:\Windows\System32(对于32位操作系统)或C:\Windows\SysWOW64(对于64位操作系统)。 3. 重新启动软件或游戏,应该能够解决api-ms-win-core-com-l1-1-0.dll丢失的问题。 方法二:安装vc_redist运行库 1. 从微软官方网站下载vc_redist_x86.exe和vc_redist_x64.exe文件,根据你的操作系统选择下载相应的文件。 2. 运行下载的exe文件,按照提示进行安装。 3. 安装完成后,重新启动计算机,再次打开软件或游戏,应该能够解决api-ms-win-core-com-l1-1-0.dll丢失的问题。 方法三:使用api-ms-win-crt-runtime-l1-1-0.dll丢失完美解决工具 1. 下载api-ms-win-crt-runtime-l1-1-0.dll丢失完美解决工具,并解压缩文件。 2. 运行解压后的exe文件,按照提示进行操作。 3. 完成后重新启动计算机,再次打开软件或游戏,问题应该会得到解决。 以上是三种解决丢失api-ms-win-core-com-l1-1-0.dll问题的方法,你可以根据个人情况选择适合的方法进行尝试。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [api-ms-win-core-com-l1-1-0.dll文件找不到如何解决?](https://blog.csdn.net/gggiweeq/article/details/130564068)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [提示计算机丢失api-ms-win-core-timezone-l1-1-0.dll文件解决办法](https://blog.csdn.net/weixin_51554164/article/details/121118181)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值