————— 线程同步的几种技术 ——————
一、原子锁 ATOM
二、临界区 CriticalSection
临界区 可以保证线程同步
{ 以下是伪代码: 在做个之前要引入Windows 单元 ,这是Delphi封装Windows下 VC++ 所有API } CreateCriticalSection CS; InitCriticalSection(CS); {--线程1执行代码--} var I: Integer; for I := 0 to 10 do begin EnterCriticalSection(CS); Memo1.add('a'); Memo1.add('a'); LeaveCriticalSection(CS); //Sleep(500); //睡0.5 s 作用: 防止线程2饥饿 一旦被抢去线程1就没有机会执行了,线程2 中的同样道理 end; {--线程1执行的代码--} {--线程2执行代码--} var I: Integer; for I := 0 to 10 do begin EnterCriticalSection(CS); Memo1.add('b'); LeaveCriticalSection(CS); // Sleep(500); end; {--线程2执行的代码--} DeleteCriticalSection(CS)
上面的代码不重要,理解其中的思想!
临界区存在的问题!
线程执行的过程是有条不紊的执行,但是并不能每次都能很好的控制哪个线程先执行!这就造成了线程之间的饥饿竞争计算机系统资源!所以这个现象应该尽量避免!
当心存在线程饥饿!
三、事件 Event
var hEvent1,hEvent2:THandle; hEvent1:= CreateEvent(参数……); hEvent2:= CreateEvent(参数……); {线程1代码} var I: Integer; for I:= 0 to 10 do begin WaitSingleForObject(hEvent1,INFINITE{等待时间,这里是 Windows下设定的无限时间});{-->一旦通过这里的阻塞,就会设置hEvent1为无信号状态,其他线程就没有执行的权限(或者其他线程就 不得执行)} {--线程1执行代码--} SetEvent(hEvent2);//设置事件2 有信号,此时线程2执行 end; {线程1代码} {线程2代码} var I: Integer; for I:= 0 to 10 do begin WaitSingleForObject(hEvent2,INFINITE{等待时间,这里是 Windows下设定的无限时间});{-->一旦通过这里的阻塞,就会设置hEvent1为无信号状态,其他线程就没有执行的权限(或者其他线程就 不得执行)} {--线程2执行代码--} SetEvent(hEvent1);//设置事件1 有信号,此时线程1执行 end; {线程2代码}
创建两个事件就可以有条不紊的执行,而且还可以控制线程执行的顺序,这样还避免了线程饥饿问题
四、互斥锁
var hMutex:THandle; hMutex := CreateMutex(参数……); {线程1代码} WaitforSingleObject(hMutex,INFINITE); {线程1执行代码} ReleaseMutex(hMutex); {线程1代码} {线程2代码} WaitforSingleObject(hMutex,INFINITE); {线程1执行代码} ReleaseMutex(hMutex); {线程2代码}
互斥锁方法与其他方法相比的好吃就是 互斥锁可以跨进程之间线程同步
当心存在线程饥饿!
五、信号量