一、临界区和竞争条件
一)、相关介绍
1、临界区就是访问和操作共享数据的代码段。
2、如果两个执行线程有可能处于同一个临界区中同时执行,那么这就是程序包含的一个bug。如果这种情况发生了,就称它为竞争条件。
3、避免并发和防止竞争条件称为同步。
二)、竞争条件实例
二、加锁
一)、相关介绍
1、锁机制提供了一种方法确保一次有且只有一次对数据进行操作,或者当另一个线程对临界区标记时,就禁止(或者说锁定)其他访问。
2、锁的使用是自愿的,非强制性的,它完全属于一种编程者自选的编程手段。
3、Linux各种锁机制之间的区别主要在于:当锁已经被其他线程持有,因而不可用时的行为表现——一些锁被争用时会简单地执行忙等待,而另外一些锁会使当前任务睡眠直
到锁可用为止。
二)、造成并发执行的原因:
1、中断——中断几乎可以在任何时刻异步发生,也就可能随时打断当前正在执行的代码。
2、软中断和tasklet——内核能在任何时刻唤醒或调度软中断和tasklet,打断当前正在执行的代码。
3、内核抢占——因内核具有抢占性,所以内核中的任务可能会被另一任务抢占。
4、睡眠以及用户空间的同步——在内核执行的进程可能会睡眠,这就会唤醒调度程序,从而导致一个新的用户程序执行。
5、对称多处理——两个或多个处理器可以执行代码。
三)、了解要保护什么
1、找出那些数据需要保护是关键所在。
2、大多数内核树据结构都需要加锁。有一个很好的经验可以帮助我们判断:如果有其他执行线程可以访问这些数据,那么就给这些数据加上某种形式的锁;如果任何其他什么
东西都能看到它,那么就要锁住它。记住,要给数据而不是代码加锁。
三、死锁
1、死锁的产生需要一定条件:要有一个或多个执行线程和一个或多个资源,每个线程都在等待其中一个资源,但所有资源都已经被占用了,所有的线程都在相互等待,但它们
永远不会释放已经占有的资源。于是任何线程都无法继续,这便意味着死锁的发生。
2、避免死锁的简单规则:
1)、按顺序加锁。
2)、防止发生饥饿。
3)、不要重复同一个锁。
4)、加锁设计应求简单。
四、争用和扩展性
1、锁的争用,或简称争用,是指当锁正在被占用时,有其他线程试图获得该锁。
2、一个锁处于高度争用状态,就是指有多个线程在等待获得该锁。
3、扩展性是对系统可扩展性的一个度量。
4、一般来说,提高可扩展性是件好事,因可提高Linux在更大型的、处理能力更强大的系统上的性能。但一味的提高可扩展性,会导致在小型SMP和UP机器上的性能降低。
5、可扩展性是很重要的,需要慎重考虑。关键在于,在设计锁的开始阶段就应该考虑到要保证良好的扩展性。