Question
Question 1:为什么m->guard = 0;释放锁放在setpark();睡眠之后
P232 代码:
queue_add(m->q, gettid());
setpark(); // new code
m->guard = 0;
Question 2:二值信号量(锁)
P264 最后,当信号量的值为负数时,这个值就是等待线程的个数。
如果有3个线程,信号量初始值为1
值 | 线程1 | 状态 | 线程2 | 状态 | 线程3 | 状态 |
1 | wait() | 运行 | 就绪 | 就绪 | ||
0 | wait()返回 | 运行 | 就绪 | 就绪 | ||
0 | 临界区开始 | 运行 | 就绪 | 就绪 | ||
0 | 中断:切换到线程2 | 就绪 | 运行 | 就绪 | ||
0 | wait() | 运行 | 就绪 | |||
-1 | sem - 1 | 运行 | 就绪 | |||
-1 | 睡眠 | 睡眠 | 运行 | |||
-1 | 中断:切换到线程3 | 睡眠 | 运行 | |||
-1 | 睡眠 | wait() | 运行 | |||
-2 | 睡眠 | sem - 1 | 运行 | |||
-2 | 睡眠 | 睡眠 | 睡眠 | |||
-2 | 睡眠 | 中断:切换到线程1 | 睡眠 | |||
-2 | 临界区结束 | 睡眠 | 睡眠 | |||
-2 | 调用post() | 睡眠 | 睡眠 | |||
-1 | 增加sem | 睡眠 | 睡眠 | |||
-1 | 唤醒线程2 | 就绪 | 睡眠 | |||
-1 | post()返回 | 就绪 | 睡眠 | |||
-1 | 中断:切换到线程2 | 就绪 | 睡眠 | |||
-1 | wait()返回? | ? | 睡眠 |
此时信号量的值为-1, 线程2是否会睡眠?
如果不会睡眠,wait()函数中是否使用了 if 判断,而不是 while?
if (sem < 0)
// 睡眠
如果使用的是 if 判断,那这个睡眠是否是永久睡眠(没有唤醒就不会运行),而不是只放弃当前时间片?
锁中线程的状态是运行态-->就绪态(只是放弃了当前的时间片,等待下一次时间片分配又会运行)
而信号量实现的锁是运行态-->睡眠态(没有人唤醒转换到就绪态就不会运行)
Noun:线程的五种状态
该实现先判断是否等待,然后再将信号量的值减1
typedef struct _Zem_t {
int value;
pthread_cond_t cond;
pthread_mutex_t lock;
};
void Zem_wait(Zem_t *s) {
s->value = value;
Cond_init(&s->cond);
Mutex_init(&s->lock);
};
void Zem_wait(Zem_t *s) {
Mutex_lock(&s->lock);
while (s->value <= 0) // 条件变量:当第一个线程运行到这里时,将会等待,直到其他线程调用post唤醒
Cond_wait(&s->cond, &s->lock);
s->value--; // 锁:当第一个线程运行到这里时,信号量的值等于0,之后的线程都将会阻塞等待,直到调用post函数。
Mutex_unlock(&s->lock);
}
void Zem_post(Zem_t *s) {
Mutex_lock(&s->lock);
s->value++;
Cond_signal(&s->cond);
Mutex_unlock(&s->lock);
}
Question 3:进程的状态如何影响线程的状态
当进程由运行态切换为阻塞态(睡眠)时,进程中的线程如何反应?是否进程中的所有线程都切换为阻塞态?
进程切换为就绪态呢?
进程切换回运行态呢?
Question 4:吸烟者问题、理发师问题
P275
Question 5:
P347:有趣的是,这段代码并不能保证你所期望的一切。在某种情况下,还需要fsync()包含foo文件的目录。添加此步骤不仅可以确保文件本身位于磁盘上,而且可以确保文件(如果新创建)也是目录的一部分。毫不奇怪,这种细节往往被忽略,,导致许多应用程序级别的错误。