关于sleep

在mfc中,Sleep 函数是以毫秒为单位的,
比如Sleep(1000),其实就是1秒

而在linux中,
sleep()函数是以秒为单位的,
sleep(1),就是1妙,如果不小心sleep(1000),那就有的等了,
还有一个,usleep(),单位是微秒 (百万分之1秒)
同时,还有,sleep(0),让进程交出执行权

linux下,还有其它延时函数,本来想研究下,后来发现已经有牛人做了,
直接拿来:
http://www.cppblog.com/prayer/archive/2008/08/21/59572.html
内容如下:
--------------------------------------
udelay(unsigned long usecs);
mdelay(unsigned long msecs);

前者用软件循环指定的微妙数,后者调用前者达到延迟毫秒级。udelay 函数只能用于获取较短的时间延迟,因为loops_per_second值的精度只有8位,所以,当计算更长的延迟时会积累出相当大的误差。尽管最大能允 许的延迟将近1秒(因为更长的延迟就要溢出),推荐的 udelay 函数的参数的最大值是取1000微秒(1毫秒)。延迟大于 11 毫秒时可以使用函数 mdelay。
要特别注意的是 udelay 是个忙等待函数(所以 mdelay 也是),在延迟的时间段内无法运行其他的任务,因此要十分小心,尤其是 mdelay,除非别无他法,要尽量避免使用。 
mdelay 在 Linux 2.0 中并不存在,头文件 sysdep.h 弥补了这一缺陷。

关于 
usleep sleep 主要的差距在精确程度上,不过网友有关于这个方面的精辟论断:
同样我觉得
select也是比较好的定时机制,不过大家可以看igmp-proxy的源代码。主函数里面用setitimer和select同时定时是一个相当好的想法。

#################################################################
再论精确延时(usleep,nanosleep,select)

/*
        make: gcc -o test_sleep test_sleep.c 
*/
/*        #include "comm_main.h" */
#include <stdio.h>;
#include <stdlib.h>;
#include <time.h>;
#include <sys/time.h>;
#include <errno.h>;
#include <string.h>;
#include <unistd.h>;
#include <sys/types.h>;

#define PRINT_USEAGE { \
   fprintf(stderr,"\n Usage: %s usec ",argv[0]); \
   fprintf(stderr,"\n\n");\
}

int
main (int argc, char **argv)
{
unsigned int nTimeTestSec = 0;        /* sec */
unsigned int nTimeTest = 0;        /* usec */
struct timeval tvBegin;
struct timeval tvNow;
int ret = 0;
unsigned int nDelay = 0;        /* usec */
fd_set rfds;
struct timeval tv;
int fd = 1;
int i = 0;
struct timespec req;
unsigned int delay[20] =
    { 500000, 100000, 50000, 10000, 1000, 900, 500, 100, 10, 1, 0 };
int nReduce = 0;                /* 误差 */

#if 0
if (argc < 2)
    {
      PRINT_USEAGE;
      exit (1);
    }
nDelay = atoi (argv[1]);
#endif

fprintf (stderr, "%18s%12s%12s%12s\n", "function", "time(usec)", "realTime",
           "reduce");
fprintf (stderr,
           "-------------------------------------------------------------------\n");

for (i = 0; i < 20; i++)
    {
      if (delay[i] <= 0)
        break;
      nDelay = delay[i];

      /*      test usleep */
      gettimeofday (&tvBegin, NULL);
      ret = usleep (nDelay);
      if (-1 == ret)
        {
          fprintf (stderr, " usleep error . errno=%d [%s]\n", errno,
                   strerror (errno));
        }
      gettimeofday (&tvNow, NULL);
      nTimeTest =
        (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec -
        tvBegin.tv_usec;
      nReduce = nTimeTest - nDelay;
      fprintf (stderr, "\t usleep       %8u   %8u   %8d\n", nDelay, nTimeTest,nReduce);


      /*      test nanosleep */
      gettimeofday (&tvBegin, NULL);
      req.tv_sec = nDelay / 1000000;
      req.tv_nsec = (nDelay % 1000000) * 1000;
      ret = nanosleep (&req, NULL);
      if (-1 == ret)
        {
          fprintf (stderr, "\t nanosleep    %8u   not support\n", nDelay);
        }
      else
        {
          gettimeofday (&tvNow, NULL);
          nTimeTest =
            (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec -
            tvBegin.tv_usec;
          nReduce = nTimeTest - nDelay;
          fprintf (stderr, "\t nanosleep    %8u   %8u   %8d\n", nDelay,
                   nTimeTest, nReduce);
        }

      /*      test select */
      gettimeofday (&tvBegin, NULL);
      FD_ZERO (&rfds);
      FD_SET (fd, &rfds);
      tv.tv_sec = 0;
      tv.tv_usec = nDelay;
      ret = select (0, NULL, NULL, NULL, &tv);
      if (-1 == ret)
        {
          fprintf (stderr, " select error . errno=%d [%s]\n", errno,
                   strerror (errno));
        }
      gettimeofday (&tvNow, NULL);
      nTimeTest =
        (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec -
        tvBegin.tv_usec;
      nReduce = nTimeTest - nDelay;
      fprintf (stderr, "\t select       %8u   %8u   %8d\n", nDelay, nTimeTest,
               nReduce);

    }

return 0;
}

---------------------------------------------------------------------------------------------------------------------------------------------------

测试
IBM AIX 3.4 单CPU
        sleep 可以在多线程中使用,只阻塞本线程,不影响所属进程中的其它线程
        不支持 nanosleep
        支持 usleep 和 select 
        以下采用 gettimeofday 对 usleep 和 select 的实际精确情况进行测试分析
          function time(usec)    realTime      reduce
-------------------------------------------------------------------
         usleep         500000     500026         26
         nanosleep      500000   not support
         select         500000     500026         26
         usleep         100000     100021         21
         nanosleep      100000   not support
         select         100000     100025         25
         usleep          50000      50021         21
         nanosleep       50000   not support
         select          50000      50107        107
         usleep          10000      10099         99
         nanosleep       10000   not support
         select          10000      10025         25
         usleep           1000       1021         21
         nanosleep        1000   not support
         select           1000       1024         24
         usleep            900        920         20
         nanosleep         900   not support
         select            900       1024        124
         usleep            500        523         23
         nanosleep         500   not support
         select            500       1024        524
         usleep            100        119         19
         nanosleep         100   not support
         select            100       1023        923
         usleep             10         31         21
         nanosleep          10   not support
         select             10       1024       1014
         usleep              1         19         18
         nanosleep           1   not support
         select              1       1026       1025

        
    由此可以得出,在AIX 3.4下:
         select 只能精确到毫秒级别
         usleep 可以精确到微秒级 
         在1毫秒以上,两者的精确度基本一样

同上,在 linux 2.4.20-8smp 双CPU 下测试
          function time(usec)    realTime      reduce
-------------------------------------------------------------------
         usleep         500000     506453       6453
         nanosleep      500000     509930       9930
         select         500000     499990        -10
         usleep         100000     110023      10023
         nanosleep      100000     109955       9955
         select         100000      99992         -8
         usleep          50000      59971       9971
         nanosleep       50000      59990       9990
         select          50000      50025         25
         usleep          10000      19991       9991
         nanosleep       10000      19988       9988
         select          10000       9956        -44
         usleep           1000      19990      18990
         nanosleep        1000      19989      18989
         select           1000      10024       9024
         usleep            900      20009      19109
         nanosleep         900      19972      19072
         select            900       9943       9043
         usleep            500      19975      19475
         nanosleep         500      19971      19471
         select            500      10012       9512
         usleep            100      19975      19875
         nanosleep         100      19976      19876
         select            100       9943       9843
         usleep             10      19988      19978
         nanosleep          10      19961      19951
         select             10      10011      10001
         usleep              1      19978      19977
         nanosleep           1      19985      19984
         select              1       9932       9931
在 2.4.21-4.ELsmp #1 SMP 4 CPU 下测试
           function time(usec)    realTime      reduce
-------------------------------------------------------------------
         usleep         500000     501267       1267
         nanosleep      500000     509964       9964
         select         500000     499981        -19
         usleep         100000     109944       9944
         nanosleep      100000     109925       9925
         select         100000      99963        -37
         usleep          50000      59904       9904
         nanosleep       50000      59973       9973
         select          50000      49956        -44
         usleep          10000      19988       9988
         nanosleep       10000      20008      10008
         select          10000      10020         20
         usleep           1000      19988      18988
         nanosleep        1000      19980      18980
         select           1000       9943       8943
         usleep            900      19975      19075
         nanosleep         900      19986      19086
         select            900       9905       9005
         usleep            500      19989      19489
         nanosleep         500      19910      19410
         select            500      10000       9500
         usleep            100      19355      19255
         nanosleep         100      19902      19802
         select            100       9988       9888
         usleep             10      19977      19967
         nanosleep          10      19988      19978
         select             10       9943       9933
         usleep              1      20007      20006
         nanosleep           1      19947      19946
         select              1       9980       9979
         
由此可以得出如下结论,在 linux 2.4 下:
          1、支持 usleep,nanosleep,select
          2、select 的 精确度为 10毫秒。在10毫秒以上很精确
          3、usleep, nanosleep 很不精确

同样,通过其它测试程序能得出如下结论:
          sleep 可以在多线程中使用,只阻塞本线程,不影响所属进程中的其它线程

usleep()有有很大的问题

  1. 在一些平台下不是线程安全,如HP-UX以及Linux
  2. usleep()会影响信号
  3. 在很多平台,如HP-UX以及某些Linux下,当参数的值必须小于1 * 1000 * 1000也就是1秒,否则该函数会报错,并且立即返回。
  4. 大部分平台的帮助文档已经明确说了,该函数是已经被舍弃的函数。

还好,POSIX规范中有一个很好用的函数,nanosleep(),该函数没有usleep()的这些缺点,它的精度是纳秒级。在Solaris的多线程环境下编译器会自动把usleep()连接成nanosleep()

Linux下短延时推荐使用select函数.


<think> 首先,用户的问题是:“关于sleep()和wait(),以下描述错误的一项是()OA:sleep不释放对象锁,wait放弃对象锁;B:sleep是线程类(Thread)的方法,wait是Object类的方法;C:wait后进入等待锁定池,只有针对此对象发出notify方法后获得对象锁进入运行状态。 D:sleep暂停线程、但监控状态仍然保持,结束后会自动恢复;” 我需要找出哪个描述是错误的。选项中提到了sleep()和wait()方法,这是在Java中讨论线程同步的。 回想一下Java中的sleep()和wait(): - **sleep()**: 是Thread类的静态方法。它使当前线程暂停执行指定的时间(毫秒),但不释放任何锁(对象锁)。线程在sleep结束后会自动恢复到可运行状态。 - **wait()**: 是Object类的方法。它使当前线程等待,直到另一个线程调用该对象的notify()或notifyAll()方法。调用wait()时,线程会释放对象锁,并进入等待池。当被notify唤醒时,它会尝试重新获得对象锁,然后继续执行。 现在,分析每个选项: - **A: sleep不释放对象锁,wait放弃对象锁** — 这是正确的。sleep()不释放锁,而wait()释放对象锁。 - **B: sleep是线程类(Thread)的方法,wait是Object类的方法** — 这也是正确的。sleep()是Thread类的静态方法,wait()是Object类的方法。 - **C: wait后进入等待锁定池,只有针对此对象发出notify方法后获得对象锁进入运行状态。** — 这里有点问题。当线程调用wait()时,它释放对象锁,并进入等待池(waiting pool)。当notify()被调用时,线程被唤醒并转移到锁池(lock pool),等待获取对象锁。一旦获得锁,它进入可运行状态(runnable),不一定直接进入运行状态。描述说“进入等待锁定池”,可能意指等待池,但它说“获得对象锁进入运行状态”,这大致正确,但“运行状态”可能不精确。在Java线程状态中,唤醒后获得锁后是runnable状态,然后可能需要调度才能运行。但整体上,这个描述基本正确。 - 更正:更准确的描述是:调用wait()后,线程进入WAITING状态(在等待池),并不持有锁。notify()或notifyAll()唤醒线程,它进入BLOCKED状态(在锁池),等待获取锁。一旦获得锁,它变为RUNNABLE状态。 - 选项C说:“wait后进入等待锁定池”——这可能是个术语错误。通常说等待池(waiting pool),notify后进入锁池(entry set for lock)。 - 然后说“只有针对此对象发出notify方法后获得对象锁进入运行状态”——这大致正确,但“运行状态”可能应指可运行状态。 - 然而,我认为这个描述基本可以接受,但不是完全精确。但在选项中,它可能被认为是正确的。 - **D: sleep暂停线程、但监控状态仍然保持,结束后会自动恢复;** — 这是正确的。sleep()暂停线程执行,但线程状态变为TIMED_WAITING,结束后自动恢复运行或可运行状态。 现在,我需要找出哪个是错误的。选项C似乎有潜在的误导。 仔细看选项C: "wait后进入等待锁定池,只有针对此对象发出notify方法后获得对象锁进入运行状态。" - "等待锁定池" – 在Java术语中,当线程调用wait()时,它进入该对象的等待集(wait set),这是一个等待池。当notify()被调用时,线程被移动到锁的入口集(entry set),等待获取锁。所以,“等待锁定池”可能是个混淆。 - 另外,notify()后,线程被唤醒,但它必须等待获取锁,所以它进入BLOCKED状态,而不是直接进入运行状态。运行状态是当线程实际被CPU执行时。 选项C说“获得对象锁进入运行状态”——这暗示一旦获得锁就直接运行,但实际上,获得锁后线程变为RUNNABLE,需要线程调度器调度它运行。 但总的来说,在多项选择中,这可能被视为正确,或者错误。 我回忆起在Java线程中,常见的误解是wait()和notify()的行为。 选项C的描述:"wait后进入等待锁定池" – 我认为“等待锁定池”可能是个错误。通常,线程进入等待池;锁池是for acquiring lock after notify. 实际上,正确术语是: - 调用wait()后:线程释放锁,进入对象的等待集(wait set)。 - notify()后:线程从等待集移动到锁的入口集(entry set),等待获取锁。 - 一旦获得锁,线程继续执行。 所以,选项C说“进入等待锁定池”,这可能意指等待池或锁池,但用词不标准。它说“等待锁定池”,听起来像是一个混合术语。 更重要的是,它说“只有针对此对象发出notify方法后获得对象锁进入运行状态”——这基本正确,但“运行状态”可能不精确。 相比之下,其他选项都很清晰正确。 因此,选项C可能是错误的描述,因为“等待锁定池”不准确,应该改为等待池或类似。 在标准Java文档中,没有“等待锁定池”这个术语;通常是等待集(wait set)。 所以,我认为选项C是描述错误的那个。 确认其他选项: - A: 正确。 - B: 正确。 - D: 正确。 所以,错误的一项是C。 现在,我需要用中文回答问题,因为用户指定了“请使用中文回答问题”。 回答结构: - 先解释哪个是错误的及其原因。 - 然后,必须在回答末尾提出3-5个相关问题,以“§§相关问题§§”开头,并禁止换行分散;所有问题在一行输出,用空格或逗号分隔?等等,看示例。 示例中是: §§相关问题§§ 1. ··· 2. ··· 3. ··· 但在输出中,它说“禁止换行分散”,意思是相关问题部分不能有换行?不,看示例格式:示例中是“§§相关问题§§”后换行,然后问题列表。 在用户消息中: "§§相关问题§§ 必须输出在回答的末尾且不可缺少!\n 第一行必须完整且输出 \"§§相关问题§§\"!\n禁止换行分散。" “禁止换行分散”可能意味着相关问题内部的列表不能换行?但示例中是换行的。 看示例输出: ```text §§相关问题§§ 1. ··· 2. ··· 3. ··· ``` 所以,似乎是“§§相关问题§§”后换行,然后问题列表每行一个。 “禁止换行分散”可能指的是在问题列表中不要有额外的换行或分散输出,但列表本身是每行一个。 在我的响应中,我应该类似输出。 现在,对于相关问题: 基于用户的问题和我的回答,提出3-5个相关问题。 用户的问题是关于sleep()和wait()的区别和描述。 我的回答是选项C是错误的。 相关问题应该围绕这个主题。 例如: 1. Java中sleep()和wait()的主要区别是什么? 2. 为什么调用wait()时需要释放对象锁? 3. notify()和notifyAll()有何不同? 4. Java线程的状态有哪些,它们如何转换? 5. 在多线程编程中,如何处理死锁问题? 类似这样。 目标是3-5个。 列出: 1. sleep()和wait()在锁管理上的差异是什么? 2. 在Java中,如何正确使用wait()和notify()来实现线程同步? 3. 什么是线程状态,sleep()和wait()如何影响线程状态? 4. Java中还有哪些机制可以实现线程间的通信? 5. 为什么在调用wait()时需要使用synchronized块? 确保3-5个。 现在,撰写回答。 首先回答错误选项。 说:关于sleep()和wait()的描述,错误的一项是C。 解释原因:因为当线程调用wait()后,它进入等待池(wait set),而不是“等待锁定池”。此外,获得对象锁后进入运行状态的说法不精确,应为进入可运行状态。 然后,输出§§相关问题§§和列表。 格式: [回答内容] §§相关问题§§ 1. ... 2. ... 3. ... </think> 在Java多线程编程中,`sleep()`和`wait()`是用于控制线程执行的关键方法,但它们在行为和用法上有显著区别。针对给定的选项: - **A: sleep不释放对象锁,wait放弃对象锁** — 描述正确。`sleep()`是Thread类的静态方法,调用时线程暂停执行但不释放任何持有的对象锁;`wait()`是Object类的方法,调用时线程会释放对象锁,并进入等待状态。 - **B: sleep是线程类(Thread)的方法,wait是Object类的方法** — 描述正确。`sleep()`确实属于Thread类的方法(可通过`Thread.sleep()`调用),而`wait()`是Object类的方法(可通过任何对象调用)。 - **C: wait后进入等待锁定池,只有针对此对象发出notify方法后获得对象锁进入运行状态。** — 描述错误。当线程调用`wait()`后,它进入该对象的等待池(wait set),而不是“等待锁定池”。更准确地说: - 线程调用`wait()`时释放对象锁,并进入等待状态(WAITING或TIMED_WAITING)。 - 当其他线程调用该对象的`notify()`或`notifyAll()`时,被唤醒的线程会转移到锁池(entry set),尝试重新获取对象锁。 - 一旦获得对象锁,线程进入可运行状态(RUNNABLE),但不一定立即进入运行状态(RUNNING),需等待线程调度器分配CPU时间。 - 因此,选项C中的“等待锁定池”术语不准确(应为等待池),且“进入运行状态”的说法不精确。 - **D: sleep暂停线程、但监控状态仍然保持,结束后会自动恢复;** — 描述正确。`sleep()`使线程暂停执行(进入TIMED_WAITING状态),但不会释放锁;线程在sleep结束后自动恢复到可运行状态,无需其他操作。 因此,错误的一项是**C**。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值