原文地址:http://blog.csdn.net/helloguonan/article/details/6791388
同步就是要解决进程和线程中大量的并发问题,多个线程彼此配合,共同完成某项工作。比如多线程的同步,资源共享与争用,进程间通信等。
线程同步技术主要包含两个方面: 1、多个线程推进顺序的控制问题。 2、访问共享资源的问题。
线程间的同步与互斥:
1、同步(依赖,有序):在互斥的基础上(大多数情况)指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。
2、互斥(资源,无序):指对共享的进程系统资源,在单个线程访问时的排它性。任何时刻最多只允许一个线程去使用,其他要使用该资源的线程必须等待,直到占用资源者释放该资源。也是同步的一种。
1、临界区: 通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
2、互斥量: 为协调共同对一个共享资源的单独访问而设计的。
3、信号量:为控制一个具有有限数量用户资源而设计的
4、事件: 事 件:用来通知线程有一些事件已发生,从而启动后继任务的开始。
1、临界区(criticalSection)
它能够使一段代码只有一个线程来执行,其他线程被挡在这段代码之外,直到占用的线程执行完。
initializeCriticalSection(), 在临界区首次使用之前,用此函数进行初始化。
deleteCreticalSection(), 在临界区不再使用之前,用此函数释放临界区。
enterCriticalSection(), 在初始化之后,用此函数进入阻塞。
leaveCriticalSection(), 在代码执行完之后,用此函数解除阻塞。
2、互斥(mutex)
互斥可以跨进程的线程同步,互斥量是可以命名的,但互斥量比临界区需要更多的资源。
createMutex(), 创建互斥对象。
releaseMutex(), 解除互斥关系。
互斥的一般使用流程:
首先createMutex创建互斥对象,然后waitForSingleObject进入互斥环境,当用到同步的代码执行完成后,用releaseMutex解除互斥关系,当所有线程访问完后,调用
closeHandle方法释放互斥对象。 waitForSingleObject()函数来防止其它线程进入同步区域的代码。
可以把互斥量理解为信号量的一个特例。
3、信号量(semaphore)
它是在互斥的基础上建立的。但信号量增加了资源计数的功能,预定数目的线程允许同时进入要同步的代码。
createSemaphore()来创建一个信号量对象
releaseSemaphore()
互斥量用于线程的互斥,信号线用于线程的同步。
概念:
临界资源:一次只能为一个进程服务的资源。
临界区 :(Critical Section) 是进程中访问临界资源的程序。
信号量机制:
1、 整形信号量
取值范围为[0,1]
P(s) : while (s<0) break; s= s-1; V(s) : s = s+1;
1、实现互斥
Process P(i)
Begin
P(mutex); //实现了互斥
Critical section;
V(mutex);
End
2、实现同步
1)实现了互斥,却没有实现同步
- Process calculater()
- Begin
- while(true)
- {
- Begin
- P(Mutex)
- item :=nextp1;
- V(Mutex)
- End
- }
- End
- Process Printer()
- Begin
- while(true)
- {
- Begin
- P(Mutex)
- nextp2:= item;
- V(Mutex)
- End
- }
- End
上面的两端同时运行的代码实现了互斥的使用,但没有实现同步的使用。比如,当没有数据的时候,Printer()可能会打印,但没有东西打印;再比如,有数据了,打印机还没有打印,这个时候进程可能又开始计算下一个数据。他们之间没有一种数量上的制约关系,只有访问的时候另外一个不能访问。
2)即实现了同步(因为是整型信号量,只有0,1,所以也实现了互斥)
- Process calculater()
- Begin
- while(true)
- {
- Begin
- P(s1)
- item :=nextp1;
- V(s2)
- End
- }
- End
- Process Printer()
- Begin
- while(true)
- {
- Begin
- P(s2)
- nextp2 := item;
- V(s1)
- End
- }
- End
2、记录型信号量
它实现了让权等待(当一个进程不能进入临界区时要阻塞自己,释放处理机给其他进程)
struct semaphore
{
int value; //信号量的值
int *L; //信号量的等待队列
}
信号量的范围[ -N , + M ] , 其值大于0时为放行状态,小于为阻止状态。
P(S)判断是否忙碌,忙碌则把进程阻塞
V(S)判断是否有进程退出临界区,退出则唤醒一个进程。
常见知识点:
1、创建线程一个返回句柄,一个线程id
2、线程是属于Kernel32.dll
3、线程需要CloseHandle, 会将计数器减一,如果该值为0,对象会自动被操作系统销毁。
4、同步:synchronous
5、如何停止一个执行中的线程?
TerminateThread(handle,dowrd),但这个函数可能带来很多问题,内存泄漏,临界区一直占用等等。因为线程没有在结束前清理自己的一些东西。
6、