vc多线程

来源:互联网 发布:淘宝书籍特种经营认证 编辑:程序博客网 时间:2024/05/22 08:08

一些概念

进程和线程的概念: 套用 孙鑫的来说 进程就好像一个手术室.线程就是里面的医生,线程当中一定有一个主线程也就是程序里的main或winmain.记住代码不是线程.代码相当于医生的手术方案,你完成了手术方案,你医生就完成工作了.  也就是说代码的结束相当于线程的结束.一个进程当中可以有1个以上的线程.当然在程序当中你必须自己创建新的线程咯.

我们可以当创建一个新线程为主刀医生叫一个新的助手

创建线程:CreateThread()第一个参数表明安全性 指向SECURITY_DESCRIPTOR 我们设为NULL,默认安全性 ,//因为助手做的事不大,所以对他的安全放低

                                             第二个参数创建线程的栈的大小 以字节为单位.我们可以设为0 表明创建与调用此函数的线程默认大小的栈 //就当提供给助手和叫他来的人一样多的器具吧

                                             第三个参数函数地址 表明线程进入的函数地址的入口点 ,//就是告诉助手 他要实行的方案 在某个地方

                                             第四个参数设为CREATE_SUSPENDED表明创建后不运行,直到ResumeThread调用才执行,设为0表明创建后就让他执行.

                                             第五个参数表明ID  //对ID不感兴趣 不接收 设为NULL 

时间片:每个线程都有一段执行的时期. 形象点说,如果手术不大,要不了多少时间的话,可能主刀医生一个人做完了但他不能预料进展还是叫了两个助手,其余两个助手没时间上场,因为整个手术时间短了刚好是主刀医生所做的.当然可能手术较大,主刀医生迅速做完了前面的没他事了,剩余其他的大量重复性工作,他可以留给助手做,在他休息睡觉这段时期,两个助手可以轮流做他们的事,例如1号助手做两分钟,2号做两分钟,然后又1号,就这样循环,直到主刀医生睡醒后,叫他们够了然后整个就结束了.

 

互斥对象:内核对象还包含了线程ID和使用计数   可以把它当成一把智能的钥匙.

创建互斥对象:

HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOLbInitialOwner, LPCTSTRlpName);

第一个参数 表明安全性NULL 第二个参数表明调用他的线程是要要获得互斥对象的权限true则为是 最后一个表明创建互斥对象的名字为NULL则为匿名

调用成功则返回 互斥对象句柄.

如果在创建的一个命名的互斥对象之前已经有了这个命名对象,则会返回之前的互斥对象句柄.可以根据GetLastError()==ERROR_ALREADY_EXISTS判断之前是否已经有了一个同名的互斥对象存在了,所以根据这个可以让程序只运行一个实例,就像一些游戏一样.

 

获得互斥对象的权限

除了在创建的时候指定获得权限外,还可以调用DWORD WaitForSingleObject( HANDLE hHandle, DWORDdwMilliseconds);此函数获得互斥对象的所有权,第一个参数要获得的互斥对象的句柄,第二个等待的时间以毫秒为单位 指定为INFINITE将一直等待. 

互斥对象将其当做一把智能钥匙,如果这把智能钥匙已经在别人手里掌握了拥有权限的话,那么它将是无信号的.

除非调用此函数的线程ID==拥有此互斥对象的ID  不过如果已经拥有了的话 你再去调用此函数 会将计数器+1

 

释放互斥对象.

规则:谁有这把钥匙,就由谁来释放它的权限.

还有一种情况就是 线程结束了,自动释放它的拥有权限.

BOOL ReleaseMutex( HANDLE hMutex);  //这个参数就不解释了

 

实例代码:

#include <windows.h>
#include <iostream.h>

DWORD WINAPI Fun1Proc(
  LPVOID lpParameter   // thread data
);

DWORD WINAPI Fun2Proc(
  LPVOID lpParameter   // thread data
);
int index=0;
int tickets=100;
HANDLE hMutex;
void main()
{
 HANDLE hThread1;
 HANDLE hThread2;
 hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);  
 hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
 CloseHandle(hThread1);//这里并不代表把线程关掉 只是不需要引用了创建的线程句柄而已
 CloseHandle(hThread2);//这里并不代表把线程关掉 只是不需要引用了创建的线程句柄而已

 /*while(index++<1000)
  cout<<"main thread is running"<<endl;*/
 //hMutex=CreateMutex(NULL,TRUE,NULL);
 hMutex=CreateMutex(NULL,TRUE,"tickets");
 if(hMutex)
 {
  if(ERROR_ALREADY_EXISTS==GetLastError())
  {
   cout<<"only instance can run!"<<endl;
   return;
  }
 }
 WaitForSingleObject(hMutex,INFINITE);
 ReleaseMutex(hMutex);
 ReleaseMutex(hMutex);
 Sleep(4000);
// Sleep(10);
}

DWORD WINAPI Fun1Proc(
  LPVOID lpParameter   // thread data
)
{
 /*while(index++<1000)
  cout<<"thread1 is running"<<endl;*/
 
 /*while(TRUE)
 {
  //ReleaseMutex(hMutex);
  WaitForSingleObject(hMutex,INFINITE);
  if(tickets>0)
  {
   Sleep(1);
   cout<<"thread1 sell ticket : "<<tickets--<<endl;
  }
  else
   break;
  ReleaseMutex(hMutex);
 }*/

 WaitForSingleObject(hMutex,INFINITE);
 cout<<"thread1 is running"<<endl;
 return 0;
}

DWORD WINAPI Fun2Proc(
  LPVOID lpParameter   // thread data
)
{
 
 /*while(TRUE)
 {
  //ReleaseMutex(hMutex);
  WaitForSingleObject(hMutex,INFINITE);
  if(tickets>0)
  {
   Sleep(1);
   cout<<"thread2 sell ticket : "<<tickets--<<endl;
  }
  else
   break;
  ReleaseMutex(hMutex);
 }*/
 WaitForSingleObject(hMutex,INFINITE);
 cout<<"thread2 is running"<<endl;
 return 0;
}

 

                                           

原创粉丝点击