并发和静态

发布时间:2016-12-11 18:02:25 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"并发和静态",主要涉及到并发和静态方面的内容,对于并发和静态感兴趣的同学可以参考一下。

现代的计算机系统都是并发的系统,也就是说多个任务在同时执行。这些同时执行的任务,往往需要使用相同的硬件或软件资源,术语叫做资源共享。硬件资源是天然共享,如网卡,硬盘等等,有QQ、网页浏览器等等大量的任务会同时使用他们。也有很多软件资源是共享的,尤其是内核资源,比如驱动以及全局变量。 有很多情况会导致多个执行者同时使用共享的资源,如SMP的多个处理器可能同时执行同一段代码,单处理器也会分时间片执行多个任务,这些任务也会执行同一段代码。中断、信号等异步事件机制也会导致多个执行者同时使用同一资源。比如主流程正在访问一个资源,这时中断来了,系统转取执行中断服务程序,而这中断服务程序也可能回访问这个资源。内核的延迟执行机制如workqueue、tasklet、定时器等也是一种异步事件 当多个执行者都试图使用共享的资源时,这种情况就叫做竞态(race condition),也叫竞争。 竞争会给我们带来很多麻烦,所以最好就是在设计时就避免资源的共享,只有在必须的时候才使用全局变量。 当然,资源共享是不可避免的,原则上,只有用户空间只要把指针传给内核函数,那么这个指针指向的用户空间都可能是共享的,虽然用户空间的资源只是本用户所有。 合理使用共享资源注意两个原则: 1)凡是对共享资源的访问都是显式的进行管理,在同一时刻只有一个用户在访问,也就是采用互斥机制,使用前先把资源锁定住。 2)需要跟踪对共享资源的访问,当还有用户在使用这个资源时,必需保证资源正常提供它的功能,在没有用户使用它时,才运行释放资源 一、信号量和互斥体       信号量设定一个临界区,在临界区内,同一时刻只有一个线程执行。只有获得信号量的线程才会进入临界区,没有获得信号量的线程则进入休眠状态,直到有其他线程释放信号量,唤醒该进程,然后才进入临界区      一个信号量本质是一个整数值和与这个整数值相关联的函数:P函数和V函数。希望进入临界区的线程调用P函数,如果整数值大于0,线程获得了信号量,可以进入临界区,并将整数值减一;如果整数值等于0,线程没有获得信号量;线程出临界区时调用V函数,将整数值加一,唤醒其它等待的线程。I/O访问和kmalloc都是可能使线程进入休眠状态的调用。 信号量的定义和相关函数在头文件<asm/semaphore.h>中 有两种方式定义并初始化信号量 1)     先定义变量:struct semaphore sem;     然后调用下列函数:     void sema_init(struct semaphore *sem, int val); 或    init_MUTEX(sem); 或   init_MUTEX_LOCKED(sem);   init_MUTEX_LOCKED与init_MUTEX的区别是init_MUTEX初始化时没有锁住信号量,init_MUTEX_LOCKED初始化时就锁住了信号量;  init_MUTEX_LOCKED与init_MUTEX都是定义的一个宏,其实也是调用sema_init函数 2)     无需先定义semaphore变量,直接调用函数      DECLARE_MUTEX(sem); 几个P函数的实现函数: extern void down(struct semaphore *sem); extern int __must_check down_interruptible(struct semaphore *sem); extern int __must_check down_killable(struct semaphore *sem); extern int __must_check down_trylock(struct semaphore *sem); extern int __must_check down_timeout(struct semaphore *sem, long jiffies); 调用down时,如果能正常获得信号量,则继续执行临界区的代码;如果没有获得,则进入休眠状态; down_interruptible是可中断的,当产生中断时,函数退出休眠状态,并返回非零值;所以down_interruptible返回时并不一定获得了信号量,还要检查返回值是否为0; down_trylock则不管释放获得信号量,都直接返回。得到则返回0;没得到就返回非0; V函数的实现只有一个: extern void up(struct semaphore *sem); <linux/semaphore.h>头文件内容 读取者/写入者信号量 信号量不管是读还是写都需要先把共享资源锁住,然后才执行临界区代码;但是当多个线程都只是读取某个资源,并不修改资源时,几个线程是可以同时执行的。 读取者/写入者信号量正好适用这种情况,虽然在实际的驱动程序开发中,比较少用,但偶尔也会用到。 需要注意的是,读取者/写入者信号量可能导致读取者饥饿,因为读取者/写入者信号量其实是写优先的,写锁时,无法获取读锁。 1)定义变量并初始化    struct rw_semaphore sem;    void init_rwsem(struct rw_semaphore *sem); 2)读锁的几个相关函数 extern void down_read(struct rw_semaphore *sem); extern int down_read_trylock(struct rw_semaphore *sem); extern void up_read(struct rw_semaphore *sem); 3)写锁的几个相关函数 extern void down_write(struct rw_semaphore *sem); extern int down_write_trylock(struct rw_semaphore *sem); extern void up_write(struct rw_semaphore *sem); extern void downgrade_write(struct rw_semaphore *sem); 使用与信号量一样,当写锁被某个线程占用时,读锁和写锁都无法获得;读锁被占用时,都锁还是可以被其他的线程读锁住;downgrade_write函数虽然线程没有释放写锁, 但是别的线程可以使用读锁了。 <linux/rwsem.h>头文件内容: complete 1)定义变量并初始化 DECLARE_COMPLETION(work) 或 struct completion compl; void init_completion(struct completion *x); 2)等待事件完成 void wait_for_completion(struct completion *); 3)事件完成 extern void complete(struct completion *); extern void complete_all(struct completion *);     <linux/completion.h>头文件内容:

上一篇:[置顶] Typedef 用法总结
下一篇:Java程序如何自动在线升级

相关文章

关键词: 并发和静态

相关评论