表 表哥 Unregistered / Unconfirmed GUEST, unregistred user! 2003-07-25 #3 最简单的是调用函数Synchronize(),你可以看看在线帮助。
T thx1180 Unregistered / Unconfirmed GUEST, unregistred user! 2003-07-25 #4 ★★★关于线程同步: Synchronize()是在一个隐蔽的窗口里运行,如果在这里你的任务很繁忙,你的主窗口 会阻塞掉;Synchronize()只是将该线程的代码放到主线程中运行,并非线程同步。 临界区是一个进程里的所有线程同步的最好办法,他不是系统级的,只是进程级的, 也就是说他可能利用进程内的一些标志来保证该进程内的线程同步,据Richter说 是一个记数循环;临界区只能在同一进程内使用; 临界区只能无限期等待,不过2k增加了TryEnterCriticalSection函数实现0时间等待。 互斥则是保证多进程间的线程同步,他是利用系统内核对象来保证同步的。 由于系统内核对象可以是有名字的,因此多个进程间可以利用这个有名字的内核对象 保证系统资源的线程安全性。互斥量是Win32 内核对象,由操作系统负责管理; 互斥量可以使用WaitForSingleObject实现无限等待,0时间等待和任意时间等待。 1. 临界区 临界区是一种最直接的线程同步方式。所谓临界区,就是一次只能由 一个线程来执行的一段代码。如果把初始化数组的代码放在临界区内,另 一个线程在第一个线程处理完之前是不会被执行的。 在使用临界区之前,必须使用InitializeCriticalSection()过程来初始化它。 在第一个线程调用了EnterCriticalSection()之后,所有别的线程就不能 再进入代码块。下一个线程要等第一个线程调用LeaveCriticalSection()后才 能被唤醒。 2. 互斥 互斥非常类似于临界区,除了两个关键的区别:首先,互斥可用于跨 进程的线程同步。其次,互斥能被赋予一个字符串名字,并且通过引用此 名字创建现有互斥对象的附加句柄。 提示:临界区与事件对象(比如互斥对象)的最大的区别是在性能上。临 界区在没有线程冲突时,要用10 ~ 15个时间片,而事件对象由于涉及到系统 内核要用400~600个时间片。 当一个互斥对象不再被一个线程所拥有,它就处于发信号状态。此时首先 调用WaitForSingleObject()函数的线程就成为该互斥对象的拥有者,此互斥 对象设为不发信号状态。当线程调用ReleaseMutex()函数并传递一个互斥对象 的句柄作为参数时,这种拥有关系就被解除,互斥对象重新进入发信号状态。 可以调用函数CreateMutex()来创建一个互斥量。 当使用完互斥对象时,应当调用CloseHandle()来关闭它。 3. 信号量 另一种使线程同步的技术是使用信号量对象。它是在互斥的基础上建立的, 但信号量增加了资源计数的功能,预定数目的线程允许同时进入要同步的代码。 可以用CreateSemaphore()来创建一个信号量对象, 因为只允许一个线程进入要同步的代码,所以信号量的最大计数值(lMaximumCount) 要设为1。ReleaseSemaphore()函数将使信号量对象的计数加1; 记住,最后一定要调用CloseHandle()函数来释放由CreateSemaphore()创建 的信号量对象的句柄。 ★★★WaitForSingleObject函数的返值: WAIT_ABANDONED指定的对象是互斥对象,并且拥有这个互斥对象的线程在没有 释放此对象之前就已终止。此时就称互斥对象被抛弃。这种情况下,这个互斥对象 归当前线程所有,并把它设为非发信号状态; WAIT_OBJECT_0 指定的对象处于发信号状态; WAIT_TIMEOUT等待的时间已过,对象仍然是非发信号状态; 自己也不记得在哪个帖子里帖过了,再帖一次。
★★★关于线程同步: Synchronize()是在一个隐蔽的窗口里运行,如果在这里你的任务很繁忙,你的主窗口 会阻塞掉;Synchronize()只是将该线程的代码放到主线程中运行,并非线程同步。 临界区是一个进程里的所有线程同步的最好办法,他不是系统级的,只是进程级的, 也就是说他可能利用进程内的一些标志来保证该进程内的线程同步,据Richter说 是一个记数循环;临界区只能在同一进程内使用; 临界区只能无限期等待,不过2k增加了TryEnterCriticalSection函数实现0时间等待。 互斥则是保证多进程间的线程同步,他是利用系统内核对象来保证同步的。 由于系统内核对象可以是有名字的,因此多个进程间可以利用这个有名字的内核对象 保证系统资源的线程安全性。互斥量是Win32 内核对象,由操作系统负责管理; 互斥量可以使用WaitForSingleObject实现无限等待,0时间等待和任意时间等待。 1. 临界区 临界区是一种最直接的线程同步方式。所谓临界区,就是一次只能由 一个线程来执行的一段代码。如果把初始化数组的代码放在临界区内,另 一个线程在第一个线程处理完之前是不会被执行的。 在使用临界区之前,必须使用InitializeCriticalSection()过程来初始化它。 在第一个线程调用了EnterCriticalSection()之后,所有别的线程就不能 再进入代码块。下一个线程要等第一个线程调用LeaveCriticalSection()后才 能被唤醒。 2. 互斥 互斥非常类似于临界区,除了两个关键的区别:首先,互斥可用于跨 进程的线程同步。其次,互斥能被赋予一个字符串名字,并且通过引用此 名字创建现有互斥对象的附加句柄。 提示:临界区与事件对象(比如互斥对象)的最大的区别是在性能上。临 界区在没有线程冲突时,要用10 ~ 15个时间片,而事件对象由于涉及到系统 内核要用400~600个时间片。 当一个互斥对象不再被一个线程所拥有,它就处于发信号状态。此时首先 调用WaitForSingleObject()函数的线程就成为该互斥对象的拥有者,此互斥 对象设为不发信号状态。当线程调用ReleaseMutex()函数并传递一个互斥对象 的句柄作为参数时,这种拥有关系就被解除,互斥对象重新进入发信号状态。 可以调用函数CreateMutex()来创建一个互斥量。 当使用完互斥对象时,应当调用CloseHandle()来关闭它。 3. 信号量 另一种使线程同步的技术是使用信号量对象。它是在互斥的基础上建立的, 但信号量增加了资源计数的功能,预定数目的线程允许同时进入要同步的代码。 可以用CreateSemaphore()来创建一个信号量对象, 因为只允许一个线程进入要同步的代码,所以信号量的最大计数值(lMaximumCount) 要设为1。ReleaseSemaphore()函数将使信号量对象的计数加1; 记住,最后一定要调用CloseHandle()函数来释放由CreateSemaphore()创建 的信号量对象的句柄。 ★★★WaitForSingleObject函数的返值: WAIT_ABANDONED指定的对象是互斥对象,并且拥有这个互斥对象的线程在没有 释放此对象之前就已终止。此时就称互斥对象被抛弃。这种情况下,这个互斥对象 归当前线程所有,并把它设为非发信号状态; WAIT_OBJECT_0 指定的对象处于发信号状态; WAIT_TIMEOUT等待的时间已过,对象仍然是非发信号状态; 自己也不记得在哪个帖子里帖过了,再帖一次。
表 表哥 Unregistered / Unconfirmed GUEST, unregistred user! 2003-07-28 #5 谢谢thx1180大侠提醒! 不过我认为同步的目的是防止临界值使用冲突,Synchronize函数至少是实现和主线程的同步,而且一般程序也就是线程和主线程之间进行数据传送。Synchronize ,临界区也好,互斥也好,说到底层应该是一样的概念吧,虽然手段不同,最后目标都是在某一时刻独占某些数据,不知我的这种观念对不对,请批评指正。 另外,能不能详细介绍一下delphi中临界区和互斥信号的使用方法,最好有代码例子,以飨我辈初学者。
谢谢thx1180大侠提醒! 不过我认为同步的目的是防止临界值使用冲突,Synchronize函数至少是实现和主线程的同步,而且一般程序也就是线程和主线程之间进行数据传送。Synchronize ,临界区也好,互斥也好,说到底层应该是一样的概念吧,虽然手段不同,最后目标都是在某一时刻独占某些数据,不知我的这种观念对不对,请批评指正。 另外,能不能详细介绍一下delphi中临界区和互斥信号的使用方法,最好有代码例子,以飨我辈初学者。
T thx1180 Unregistered / Unconfirmed GUEST, unregistred user! 2003-07-29 #6 建议看看《Delphi 5开发人员指南》第十一章,里面讲的很清楚,也有例子,下载: http://www.codestudy.net/book/list.asp?id=497 http://www.codestudy.net/book/subclass.asp?id=22&classid=16&page=8
建议看看《Delphi 5开发人员指南》第十一章,里面讲的很清楚,也有例子,下载: http://www.codestudy.net/book/list.asp?id=497 http://www.codestudy.net/book/subclass.asp?id=22&classid=16&page=8
D dedema Unregistered / Unconfirmed GUEST, unregistred user! 2003-07-29 #7 var Section:TRTLCriticalSection; begin InitializeCriticalSectionAndSpinCount(Section); EnterCriticalSection(Section); //要保护的资源在这里访问. LeaveCriticalSection(Section); end;
var Section:TRTLCriticalSection; begin InitializeCriticalSectionAndSpinCount(Section); EnterCriticalSection(Section); //要保护的资源在这里访问. LeaveCriticalSection(Section); end;