线程同步用来对资源的一种控制使用,避免产生死锁。
一. critical section
只能在进程之内使用, 不属于内核变量,当对资源进行critical section以后,只有获得所有权的线程,才能对资源的访问,访问过后,退出以后,其它线程才能访问资源,由于不属于内核变量,时间快,效率高。
注:如果有线程在获得所有权以后,退出以前死掉,这时其它线程就不能获得对资源的所有权,会一直等待死在哪儿,不能在critical section里面进行sleep(),wait()操作。
二. 互斥量Mutexes
属于内核变量,所以要花费大量时间,但是可以在进程之间使用,用Mutexes限定资源以后,当Mutexes的使用计数为0时,wait()操作才返回,否则其它线程对资源的访问会一直等待下去。
注:为了避免死锁,在相同时间内要把进程/线程使用的所以资源全部锁住,只有同时拥有所需所有资源的所有权时,才能对资源进行访问。
三.信号量。
互斥量是为每一个资源建立一个互斥量,但是当资源过多,就需要建立很多互斥量,会导致额外的系统开销。这时就需要用到信号量了,信号量是为一堆资源建立一个信号量,当信号量为0,这时就是说没有资源可供提供,线程/进程就必须等待。
windows事件对象源码:用于控制不同线程的先后顺序
// 多线程_事件对象.cpp : Defines the entry point for the console application.
//
//程序功能说明,windows事件对象练习,用于不同线程之间的同步
/*************************************
创建两个线程,一个读线程和一个写线程,当写的线程写完以后,读线程才能读操作,当读操作完成以后
通知主进程main,完成了,然后才结束。
*************************************************/
#include "stdafx.h"
#pragma comment(lib, "ws2_32.lib")
#include <stdio.h>
#include <process.h> // 创建线程和进程的头文件
#include <WinSock2.h>
//************事件对象变量****************
WSAEVENT evToRead; //写完成后,通知对象
WSAEVENT evToFin; //读完成之后,通知主进程对象
void ReadThread(LPVOID param)
{
WSAWaitForMultipleEvents(1, &evToRead, TRUE, WSA_INFINITE, FALSE);// 等待对象操作,阻塞
printf("reading....\n");
for(int i = 9; i > 0; i--)
{
printf("%d ", i);
Sleep(500);
}
WSASetEvent(evToFin); //通知主进程main,读操作完成了
}
void WriteThread(LPVOID param)
{
printf("writing....\n");
for(int i = 9; i > 0; i--)
{
printf("%d ", i);
Sleep(500);
}
WSASetEvent(evToRead); //通知读线程,写已经完成了
}
int _tmain(int argc, _TCHAR* argv[])
{
evToFin = WSACreateEvent();
evToRead = WSACreateEvent();
_beginthread(ReadThread, 0, NULL); //线程结束的时候会自动调用,_endthread,不用调用closehandle!!
_beginthread(WriteThread, 0, NULL);
WSAWaitForMultipleEvents(1, &evToFin, TRUE, WSA_INFINITE, FALSE);//接受读完成后的通知
printf("main over\n");
return 0;
}