同步:
同步指两个或两个以上随时间变化的量在变化过程中保持一定的相对关系。
本意是指某人或某事同时进行;同时产生,比如音画同步、动作同步等。
同步(英语:Synchronization),指对在一个系统中所发生的事件(event)之间进行协调,在时间上出现一致性与统一化的现象。
保护数据不被并发访问!!!
为什么需要同步?
为了保护共享的数据资源;(群狗抢食---同时访问共享资源,出现争抢;)
多个执行流(线程)并发访问同一个资源通常是不安全的;
需要避免并发访问、竞争条件的出现;
基本概念:
临界区(临界段):访问和操作共享数据的代码段;
代码原子执行:指令流(执行代码编译而成)执行结束前不可被打断;如同一个不可分割的指令(指令集中的指令);
竞争条件(race conditions):两个或两个以上的执行线程同时访问临界区
造成并发执行有哪些原因?
1.中断---任何时刻(异步)都可能发生,打断当前执行流;
中断处理程序去访问被打断的当前执行流访问的同一资源;
在中断处理程序中能避免并发访问的安全代码称作安全中断代码(interrupt-safe);
2.软中断和tasklet---内核能在任何时刻唤醒或调度软中断和tasklet,打断当前执行流;
3内核抢占---内核具有抢占性,所以内核中的任务可能会被另一任务抢占;
在内核抢占时能避免并发访问的安全代码称为抢占安全代码(preempt-safe);
4.睡眠及用户空间的同步----内核中执行的进程可能会睡眠,会唤醒调度程序,导致调度一个新用户进程执行;
内核代码不可在临界区睡眠(占着坑,不办事)
5.对称处理---两个或两个以上的处理器可以同时执行;
多个处理器不能够访享数问同一共据;
同步机制能够恰当的使用,有一个前提:
如何辨认出需要共享的数据和相应的临界区?
什么数据需要加锁?(加锁的应当是数据而不是代码)
大多数内核数据结构都需要加锁;
若有其他线程可以访问数据,就给这些数据加锁;
若有其他任何什么东西都能看到它,加锁;
在编写内核代码时,需要搞清楚以下问题:
这个数据是不是全局的?除了当前线程,其他线程能不能访问它?
这个数据会不会在进程上下文和中断上下文中共享?会不会在两个中断处理程序中共享?
进程在访问数据时可不可能被抢占?被调度的新程序会不会访问同一数据?
当前进程是不是会睡眠(阻塞)在某些资源上?若是,会让共享数据处于何种状态?
如何防止数据失控?
如果这个函数又在另一个处理器上被调度将会发生什么呢?
如何确保代码远离并发威胁?
死锁是如何产生的?
条件:一个或多个线程、一个或多个资源
都在等待,都等不到!
如何预防死锁?
1.按顺序加锁;使用嵌套锁时必需保证以相同顺序获取锁;
2.不要重复请求一个锁
3.防止饥饿;确保代码能执行下去!
4.设计简单的加锁方案;
参考:
Linux内核设计与实现