Linux 线程间的同步与互斥

      在线程并发执行的时候,我们需要保证临界资源的安全访问,防止线程争抢资源,造成数据二义性。

      

      线程同步: 条件变量

      为什么使用条件变量?

      对临界资源的时序可控性,条件满足会通知其他等待操作临界资源的线程,类似信号。 场景:T-DAY展会排队参观/生产者消费者模型

      条件变量是什么?

      是一种同步机制,一个线程用于修改这个变量使其满足其它线程继续往下执行的条件,其它线程则接收条件已经发生改变的信号。      

      条件变量操作?

      初始化和销毁

        pthread_cond_wait

      条件不满足 会释放锁并阻塞等待 , 这个函数是原子性操作:1.将线程放入条件等待队列    2.释放锁                            

      条件满足 则线程会被唤醒并加锁

         pthread_cond_signal 一对一唤醒     

             唤醒等待队列中的一个线程

      pthread_cond_broadcast 广播唤醒

               唤醒等待队列中的全部线程       

      为什么等待和解锁需要原子操作/为什么条件变量要使用互斥锁?

      因为pthread_cond_wait中的锁是为了保护条件变量,防止错过信号,如果等待解锁不是原子性操作,比如线程A先解锁,此时CPU时间片切换到线程B,线程B加锁并发送条件变量信号,此时再切换到线程A,线程A还来不及等待就错过了信号,就可能会永久阻塞下去。所以,等待和解锁必须是原子性操作。

      为什么需要while循环判断临界资源是否存在?

      在一对多的情况下,生产者发送一个信号,等待的线程被唤醒并加锁,但是只有一个线程能加锁,其他线程就会阻塞等待锁,如果这个线程用完了临界资源,其他线程不进行判断就继续往下走,是不合理的。

      singnal要先解锁还是后解锁?

      如果先解锁,锁被没有阻塞等待的线程拿到了,再把临界资源使用了,解锁后的singal就没意义了,也就是虚假唤醒;

      先singal唤醒,再让唤醒的线程争抢锁,在linux下,有两个队列,一个是cond_wait,一个是mutex_lock,singal只是让cond_wait上的线程转移到mutex_lock,不会返回用户空间,这样能提高效率。

      

      

      线程互斥: 互斥锁

      为什么使用互斥锁?

      对临界资源同时间唯一访问,保护临界资源防止修改。 场景:黄牛抢票

      互斥锁是什么?

      是一个0/1计数器,1代表有资源能操作,0代表没有资源可以操作。

      互斥锁操作?

      初始化和销毁

      加锁---如果计数为1,置0,进行需要的操作;如果计数为0,则阻塞等待计数变为1

      解锁---计数置为1

      

      

原文地址:https://www.cnblogs.com/Duikerdd/p/11761151.html

时间: 2024-10-07 06:46:00

Linux 线程间的同步与互斥的相关文章

嵌入式开发之hi3519---进程线程间的同步和互斥,条件变量、信号了、互斥锁等

sem_post 最安全 sem  有序,会卡顿 阻塞 mutex  无序,不能同步 http://blog.chinaunix.net/uid-20671208-id-4935154.html https://www.cnblogs.com/ngnetboy/p/3521547.html http://www.jianshu.com/p/1e59f0970bf5 http://blog.csdn.net/jenny8080/article/details/52094140

linux线程间通信之条件变量和互斥量

一.条件变量定义 有的时候仅仅依靠锁住共享资源来使用它是不够的.有时候共享资源只有某些状态的时候才能够使用.比方说,某个线程如果要从堆栈中读取数据,那么如果栈中没有数据就必须等待数据被压栈.这种情况下的同步使用互斥锁是不够的.另一种同步的方式--条件变量,就可以使用在这种情况下.条件变量(Condition Variable)是线程间的一种同步机制,提供给两个线程协同完成任务的一种方法,使用条件变量可以以原子方式阻塞线程,直到某个特定条件为真为止.条件变量的测试一般是用互斥量来保护的,用来确保每

vc++高级班之多线程篇[7]---线程间的同步机制②

//示例代码: CStringArray g_ArrString; UINT __cdecl ThreadProc(LPVOID lpParameter) { int startIdx = (int)lpParameter; for (int idx = startIdx; idx < startIdx+100; ++idx) { CString str; str.Format(_T("%d"), idx); g_ArrString.Add(str); } return 0; }

vc++高级班之多线程篇[6]---线程间的同步机制①

①.线程同步的必要性: int g_Num = 0; UINT __cdecl ThreadProc(LPVOID lpParameter) { for (int idx = 0; idx < 100; ++idx) { g_Num = g_Num+1; CString strNum; strNum.Format(_T("%d"), g_Num); g_Num = g_Num-1; } return 0; } void CThreadTestDlg::OnBnClickedBtn

linux线程间同步方式汇总

抽空做了下linux所有线程间同步方式的汇总(原生的),包含以下几个: 1, mutex 2, condition variable 3, reader-writer lock 4, spin lock 5, barrier mutex是最常用的线程间同步方式,主要目的是保护共享的资源可以被原子地访问. 个人感觉condition variable是除了mutex之外的第二常用的线程间同步方式,可以用来以同步的方式使用一个线程来通知另一个线程某个事件已经发生.可以理解为线程间的信号. reade

浅析线程间通信一:互斥量和条件变量

线程同步的目的简单来讲就是保证数据的一致性.在Linux中,常用的线程同步方法有互斥量( mutex ).读写锁和条件变量,合理使用这三种方法可以保证数据的一致性,但值得的注意的是,在设计应用程序时,所有的线程都必须遵守相同的数据访问规则为前提,才能保证这些同步方法有效,如果允许某个线程在没有得到访问权限(比如锁)的情况下访问共享资源,那么其他线程在使用共享资源前都获得了锁,也会出现数据不一致的问题.另外还有自旋锁.barrier和信号量线程同步方法.本文将讨论互斥量和条件变量的使用,并给出了相

线程间的同步----利用互斥量来实现

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <pthread.h> // 包含线程库 #include <semaphore.h> // 包含信号量库 void *thread_function(void *arg); // 定义线程函数原型 pthread_mutex_t work_mutex; //

linux线程间同步(1)读写锁

读写锁比mutex有更高的适用性,可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁. 1. 当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞: 2. 当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是以写模式对它进行枷锁的线程将阻塞: 3. 当读写锁在读模式锁状态时,如果有另外线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁请求,这样可以避免读模式锁长期占用,而等待的写模式锁请求长期阻塞: 这种锁适用对数据结

线程间的同步----利用信号量来实现

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> #include <string.h> #include <semaphore.h> sem_t bin_sem; void *thread_funtion(void *arg); char work_area[1024]; int main() { pthread_t a_t