JavaScript is required to for searching.
跳过导航链接
退出打印视图
Oracle Solaris Studio 12.3:线程分析器用户指南     Oracle Solaris Studio 12.3 Information Library (简体中文)
search filter icon
search icon

文档信息

前言

1.  什么是线程分析器?它有什么作用?

2.  数据争用教程

3.  死锁教程

3.1 关于死锁

3.2 获取死锁教程源文件

3.2.1 din_philo.c 的源代码内容

3.3 哲学家就餐方案

3.3.1 哲学家如何发生死锁

3.3.2 为 1 号哲学家引入一段休眠时间

3.4 如何使用线程分析器查找死锁

3.4.1 编译源代码

3.4.2 创建死锁检测实验

3.4.3 检查死锁检测实验

3.4.3.1 使用线程分析器查看死锁检测实验

3.4.3.2 使用 er_print 查看死锁检测实验

3.5 了解死锁实验结果

3.5.1 检查出现死锁的运行

3.5.2 检查存在潜在死锁但仍可完成的运行

3.6 修复死锁和了解误报

3.6.1 使用令牌控制哲学家

3.6.1.1 误报的报告

3.6.2 另一种令牌机制

A.  线程分析器可识别的 API

B.  有用提示

3.3 哲学家就餐方案

哲学家就餐方案是一个结构如下的经典方案。编号从 0 到 4 的五位哲学家坐在圆桌旁思考。随着时间的推移,每个人开始饥饿并决定进餐。餐桌上有一盘面条,但是每位哲学家只有一根筷子可用。为了吃到面条,他们必须共用筷子。每位哲学家右边(他们面向餐桌而坐)的筷子的编号与该哲学家的编号相同。

图 3-1 哲学家就餐

image:显示哲学家和他们的筷子处于环状结构的一个图。

每位哲学家首先拿到与自己编号相同的筷子。他拿到分配给自己的筷子后,他将去拿分配给邻座的筷子。拿到两根筷子后,他就可以进餐了。吃完后,他将筷子放回桌上的原来位置,一边一根。该过程一直重复,直到把面条吃完。

3.3.1 哲学家如何发生死锁

每位哲学家都拿到自己的筷子并等待使用其邻座的筷子时,就会发生实际的死锁。

在这种情况下,没人可以吃到东西,于是哲学家们陷入了死锁之中。多次运行该程序,您将看到该程序有时会挂起,而有时又可以运行至完成。该程序挂起的情况如以下运行过程样例所示:

prompt% cc din_philo.c
prompt% a.out
Philosopher 0 is done thinking and now ready to eat.
Philosopher 2 is done thinking and now ready to eat.
Philosopher 2: got right  chopstick 2
Philosopher 2: got left chopstick 3
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 4 is done thinking and now ready to eat.
Philosopher 4: got right  chopstick 4
Philosopher 2: eating.
Philosopher 3 is done thinking and now ready to eat.
Philosopher 1 is done thinking and now ready to eat.
Philosopher 0: got right  chopstick 0
Philosopher 3: got right  chopstick 3
Philosopher 2: got right  chopstick 2
Philosopher 1: got right  chopstick 1
(hang)

Execution terminated by pressing CTRL-C

3.3.2 为 1 号哲学家引入一段休眠时间

一种避免死锁的方法是让 1 号哲学家在拿起他的筷子之前等待一段时间。就代码而言,可让他在拿起自己的筷子之前休眠指定的一段时间 (sleep_seconds)。如果他休眠的时间足够长,该程序就可能会完成而不发生任何实际死锁。可以将他休眠的秒数指定为可执行程序的参数。如果不指定参数,该哲学家就不会休眠。

以下伪代码显示了每位哲学家的逻辑:

   while (there is still food on the table)
      {
        if (sleep argument is specified and I am philosopher #1)
           {
             sleep specified amount of time
           }

        grab right fork
        grab left fork
        eat some food
        put down left fork
        put down right fork 
      }

下面列出了该程序的一次运行,在这次运行中 1 号哲学家在拿起他的筷子之前等待 30 秒。该程序运行至完成,所有五位哲学家都吃到了面条。

% a.out 30
Philosopher 0 is done thinking and now ready to eat.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 4 is done thinking and now ready to eat.
Philosopher 4: got right  chopstick 4
Philosopher 3 is done thinking and now ready to eat.
Philosopher 3: got right  chopstick 3
Philosopher 0: eating.
Philosopher 2 is done thinking and now ready to eat.
Philosopher 2: got right  chopstick 2
Philosopher 1 is done thinking and now ready to eat.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
...
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0: got right  chopstick 0
Philosopher 0: got left chopstick 1
Philosopher 0: eating.
Philosopher 0 is done eating.
Philosopher 4: got left chopstick 0
Philosopher 4: eating.
Philosopher 4 is done eating.
Philosopher 3: got left chopstick 4
Philosopher 3: eating.
Philosopher 3 is done eating.
Philosopher 2: got left chopstick 3
Philosopher 2: eating.
Philosopher 2 is done eating.
Philosopher 1: got right  chopstick 1
Philosopher 1: got left chopstick 2
Philosopher 1: eating.
Philosopher 1 is done eating.
%

Execution terminated normally

尝试多次运行该程序,并指定不同的休眠参数。如果 1 号哲学家在拿起他的筷子之前仅等待很短的一段时间,那么发生什么情况呢?如果他等待的时间更长一些,又会怎么样?尝试为可执行程序 a.out 指定不同的休眠参数。在使用或不使用休眠参数的情况下多次重新运行该程序。该程序有时会挂起,而有时又可以运行至完成。程序是否挂起取决于线程的调度情况以及线程进行锁请求的时间。