当前位置:文档之家› C语言:2.5同步与死锁

C语言:2.5同步与死锁



千锋3G嵌入式移动互联网技术研发中心
信号量
• • • • • 计数信号量:1----N 二进制信号量(互斥锁): 0,1 二进制信号量可用于解决临界区问题 计数信号量用于解决多个进程访问数量有限的资源 解决同步问题,进程1的某语句先执行,进程程2后执行
千锋3G嵌入式移动互联网技术研发中心
生产者与消费者
• • • • • 多个进程并发操作公共变量 公共变量的结果取决于执行顺序,出现竞争 并发时执行顺序不确定 解决办法:使得同时只有一个进程访问公共变量 进程同步或协调使得运行结果不会互相干扰


千锋3G嵌入式移动互联网技术研发中心
信号量
• 缺点:需要忙等,浪费CPU周期 • 优点:不需要上下文切换 • 消除忙等:
– 把等待信号量的进程转入挂起状态 – 等信号量大于零时唤醒 – 每个信号量有一个等待队列

千锋3G嵌入式移动互联网技术研发中心
监视器
• • • • • • • • • 信号量要求各个进程都符合使用规范 一个进程编程错误就会导致数据出错或死锁 一种抽象数据类型:私有数据和公共方法绑定 操作在监视器内部互斥 监视器保证进入的进程同时只能有一个处于活动状态 使用者提供条件变量用于同步 condition x x.wait 调用进程挂起 x.signal 恢复一个调用进程,若没有处于挂起的进程, 就什么效果都不发生,与信号量不同
千锋3G嵌入式移动互联网技术研发中心
临界区问题
• • • • • • • 临界区代码:修改公共变量,更新表格,写文件…... 一个进程进入临界区执行时 其它进程不能进入临界区 内核内部:打开文件列表 非抢占式内核不严重: winxp,win2000 抢占式内核问题严重:linux, solaries 解决办法应满足

千锋3G嵌入式移动互联网技术研发中心
读者写者问题

千锋3G嵌入式移动互联网技术研发中心
哲学家就餐

– P等Q离开监视器或等待另一条件变量
• signal and continue
– Q等P离开监视器或等待另一条件变量

千锋3G嵌入式移动互联网技术研发中心
监视器实现
• • • • 对每一个监视器使用一个信号量mutex,初始为1 想进入监视器进程需要先wait(mutex) 离开监视器的进程必须signal(mutex) 执行signal(mutex)的进程需要等待激 活的进程 • next(初始为0),执行signal的进程可 以在next挂起 • next_count表示在next上挂起的进程数 • 每个外部函数里都要先等待mutex
千锋3G嵌入式移动互联网技术研发中心
读者写者问题
• • • • • • • 多个并发的进程共享一个数据库 读者:只读数据库的进程 写者:更新数据库的进程 两个或多个读者同时访问,结果正确 一个写者和另外的进程去同时访问,出现混乱 变种1:读者不会因为有写者在等待而等待别的读者 变种2:写者优先,写者需要更新数据时尽快访问
Linux进程同步
• preempt_enable • preempt_disable • 处于内核态的任务持有锁时抢占是不安全的, preempt_count用于记录持有锁的数量

千锋3G嵌入式移动互联网技术研发中心
pthread同步

千锋3G嵌入式移动互联网技术研发中心
互斥锁
• • • • • • • 用锁来保护临界区 进入临界之前先申请锁 出临界区时释放锁 构造互斥锁很复杂 单处理机通过关中断实现 非抢占式内核使用 多处理机上关中断花时间


千锋3G嵌入式移动互联网技术研发中心
pthread互斥锁
• • • • 互斥锁属性pthread_mutexattr_t int pthread_mutexattr_init(pthread_mutexattr_t *attr); int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); 进程间共享属性
千锋3G嵌入式移动互联网技术研发中心
生产者与消费者
• 两个进程并发,经打断和调度后,底层的指令乱序执行
• 执行前counter 的值是5 • 执行完成后,生产者进程出错: counter ++ 得到了4 • 若T4和T5的执行顺序调换一下,消费者进程出错: counter -- 得到了6

千锋3G嵌入式移动互联网技术研发中心
死锁
• 两个或多个进程在待一个事件 • 而这个事件需要某个处于等待的进程执行signal操作

千锋3G嵌入式移动互联网技术研发中心
生产消费者问题
• int full; /* 当前缓冲区内数据个数 */ • int empty; /* 当前缓冲区内空闲的个数 */ • int mutex; /* 提供对缓冲区的互斥操作,初始化为1 */
硬件锁
• 使用交换原子操作构造锁

千锋3G嵌入式移动互联网技术研发中心
硬件锁
• 实现了有限等待的算法

千锋3G嵌入式移动互联网技术研发中心
信号量
• 锁使用复杂,多处理机上硬件实现困难 • 信号量是一个整数,有两个原子操作P和V • P(wait) V(increament)

千锋3G嵌入式移动互联网技术研发中心
监视器

千锋3G嵌入式移动互联网技术研发中心
监视器
• 为保证监视器内部同时只能一个进程处于活动状态 • 假如进程P对 x 执行 signal时, 进程Q处于挂起状态等x • signal and wait
千锋3G嵌入式移动互联网技术研发中心
Linux进程同步
• 提供了信号量和spinlock • 多处理机上是spinlock, 只能短期的持有 • 单处理机上使用信号量,通过使能内核抢占实现

千锋3G嵌入式移动互联网技术研发中心

千锋3G嵌入式移动互联网技术研发中心
生产者与消费者
• 公共变量 counter 用来记录当前缓冲区中数据个数 • 生产者填充数据后,执行 counter ++
• 消费者取出数据后,执行 counter --

千锋3G嵌入式移动互联网技术研发中心
信号量

千锋3G嵌入式移动互联网技术研发中心
信号量实现
• • • • 回归到一个临界区问题 单处理机上关中断 多处理机上忙等(spinlock) 临界区很短

– PTHREAD_PROCESS_PRIVATE – PTHREAD_PROCESS_SHARED
• int pthread_mutexattr_getpshared(const pthread_mutexattr_t * restrict attr, int *restrict pshared); • int pthread_mutexattr_setpshared( pthread_mutexattr_t *attr, int pshared);
千锋3G嵌入式移动互联网技术研发中心
欢迎您到(千锋学院)来学 习!
同步与死锁
主讲老师:欧阳坚

千锋3G嵌入式移动互联网技术研发中心
生产者与消费者
• 两个进程共享缓冲区 • 生产者进程只要发现缓冲区不满,就填充数据 • 消费者进程只要发现缓冲区内有数据,就向外取

千锋3G嵌入式移动互联网技术研发中心
pthread互斥锁
• 使用之前获得锁 int pthread_mutex_lock(pthread_mutex_t *mutex); • 不阻塞接口 int pthread_mutex_trylock(pthread_mutex_t *mutex); 正确返回0,否则返回EBUSY • 使用完释放互斥锁 int pthread_mutex_unlock(pthread_mutex_t *mutex); • 演示lockdemo
千锋3G嵌入式移动互联网技术研发中心
硬件锁
• • • • 通过原子操作TestAndSet构造锁 把lock置成true,并返回原值 返回true说明锁被人持有 返回false同时得到锁

千锋3G嵌入式移动互联网技术研发中心
• • • • • 互斥锁 条件变量 读写锁 有些实现提供了信号量 有些实现提供了spi网技术研发中心
pthread互斥锁
• pthread_mutex_t • 静态分配初始化PTHREAD_MUTEX_INITIALIZER • 动态分配初始化 int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); • 动态销毁 int pthread_mutex_destroy(pthread_mutex_t *mutex);

千锋3G嵌入式移动互联网技术研发中心
生产者

千锋3G嵌入式移动互联网技术研发中心
消费者

– 互斥 – 前进 – 有限等待

千锋3G嵌入式移动互联网技术研发中心
软件解决办法
• i 和 j 两个进程共享变量
• turn 表示允许进程进入临界区 • flag[t] 为真表示进程 t 准备进入 • 思想:两个进程互相谦让,先 谦让的先行,后让者后走 • 只是一个算法思路,无法保证 在不同架构机器上运行

千锋3G嵌入式移动互联网技术研发中心
监视器实现
• 条件变量的实现使用信号量 • 对每个信号量x提供信号量 x_sem和整数 x_count • x.wait x.signal

相关主题