死锁的四个必要条件:
①资源有限②持有等待③不能抢占④循环等待条件
死锁的应对方式:
①消除独占条件(即将资源无限增加或者变为共享)
②消除保持和请求条件(即一个进程一次请求其所需要的所有资源,而不是请求一点资源做一点事情,但是这样太过浪费。)
③消除非抢占条件(即允许对资源进行抢占)
④消除循环等待条件(即产生循环等待的原因是进程请求资源的顺序是随即的,一个进程可以先请求A资源再请求B资源,也可以反过来,这时规定对于A/B资源的请求顺序,就可以避免死锁)
银行家算法:死锁避免算法
进程间通信:
Popen和pclose
Popen(const char*cmdstring,const char* type(“r”“w”))会限制性fork,然后exec执行cmdstring,然后根据R或者W确定可读还是可写。
FIFO,有名管道。Mkfifo调用mknod创建一个FIFO文件。
无名管道:管道用于父子进程之间的通信,pipe在fork前使用,之后父子进程各自关闭不用的端口,一端进行写,一端进行读。
有名管道:弥补了必须是有血缘关系的进程间才能进行的通信,在内存中穿件FIFO文件,多个不相关的进程可以进行读写操作。管道都是半双工的。
信号量:信号量是一个计数器,用来控制多个进程对资源的访问,经常用于控制资源的访问。
共享内存:映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,多个进程都可以访问。他专门针对进程通信方式运行效率低而设计的,所以他是最快的IPC方式。
套接字:可以用于不同机器间的进程通信。
线程间的通信方式:
互斥锁:同一时间仅仅能被一个线程访问的机制,而其他试图再次进行加锁的线程将被阻塞。
自旋锁:自旋锁和互斥锁类似,但是自旋锁不会引发互斥锁的阻塞睡眠,而是一直处于忙等状态,一直占用CPU的资源。所以在使用资源时间较短并且希望降低调度上花费的成本时使用自旋锁。
读写锁:每次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占用读模式的读写锁。写加锁模式下,试图再次进行写操作的线程将阻塞。读加锁模式下,可以再次进行读加锁,写加锁将被阻塞。这样容易造成写操作的饿死,一种解决的方法是,当处于读模式的读写锁收到一个写操作的时候,便会阻塞之后的读加锁操作。
RCU锁:读,复制,更新锁。实际上是对读写锁的一种改进,他允许多个读者和写着同时访问被保护的资源。写者的同步开销取决于使用的写者间同步机制。写者修改数据前先拷贝一个副本,在副本上进行修改,当所有的读者都已经完成读操作之后,便会进行真正的拷贝,拷贝已经完成的写操作的副本到源资源中。
条件变量:以原子的方式阻塞进程,知道某个特定的条件为真。条件变量通常与互斥锁一起使用。条件变量的类型为pthread_cond_t。