前言

芒果TV中台部门位于长沙风水宝地马栏山,有同学面试给到了17k*18(四年小厂工作经验),也算长沙大厂了。线程同步是芒果tv研发岗一面必问的问题。

线程同步

多线程访问共享数据时,可能发生冲突。因此需要通过特定的方式来控制线程之间执行的顺序。举个例子,两个线程操作同一个变量,分为三个步骤:

从内存读变量到寄存器、寄存器中赋值、将寄存器值写回内存。

产生冲突的原因就在于这三个步骤不是一个原子操作,中间某一过程被中断,切换线程再对同一变量或共享资源操作,就会出现问题。

linux系统下有四种基本的线程同步方式:互斥锁、读写锁、条件变量、信号量。

互斥锁

采用加锁方法来控制对共享资源的原子操作,同一时刻只允许一个线程执行

读写锁

用于读多写少的场景,可以参考阿姨打扫男厕所时的场景

条件变量

事件通知机制,需要和互斥锁配合使用

信号量

一个可计数变量,既能用于互斥又能用于同步

几种同步方式的特点

1、互斥锁是为了上锁而设计的,条件变量是为了等待而设计的,信号量可用于上锁互斥,也可用于等待同步。

2、互斥锁必须由给它上锁的线程(持有者)解锁,信号量的释放不必由执行过它的等待操作的同一线程执行。一个线程可以等待某个给定信号量,而另一个线程可以释放该信号量。

3、实际应用通常采用互斥量+条件变量的方式,是因为其加锁的位置和等待的位置可以是两个位置,但使用信号量就不行。

4、信号量等待和释放的可能不是一个线程,可能导致更多的开销和更高的复杂性,编码不当会出现死锁问题,通常需要实现优先级继承和优先级反转。

条件变量中的唤醒丢失问题

下面是知乎的一个例子

Thread A 使用了互斥锁对操作条件变量的代码区域(临界区,包括2-4共3行代码):

1: pthread_mutex_lock(&mutex);
2: while (false == ready) {
3: pthread_cond_wait(&cond, &mutex);
4: }
5: pthread_mutex_unlock(&mutex);

Thread B 没有使用互斥锁对操作条件变量的代码区域(临界区,下面两行都属于临界区)进行保护。

1: ready = true;
2: pthread_cond_signal(&cond);

执行序列

Thread A

Thread B

1

1: pthread_mutex_lock(&mutex);

2

2: while (false == ready) {

3

1: ready = true;

4

2: pthread_cond_signal(&cond);

5

3:  pthread_cond_wait(&cond, &mutex);

6

4: }

按上面的执行序列,条件变量唤醒 signal 先于 wait,那么相当于 Thread A 还没有被加入唤醒队列(thread A进入pthread_cond_wait()之后,才会加入到待唤醒队列中),这个时候,你已经 signal 唤醒了,那么这次唤醒自然就丢失了(后续如果还调用了唤醒,则能唤醒thread A了,如果不再调用pthread_cond_signal()则thread A就不会再被唤醒,只能永远休眠),执行序列的第 5 行,也就是 Thread 的第 3 行pthread_cond_wait(&cond, &mutex) 就会一直等在那里了。

这里需要保证 ready == false 判断成立和 Thread A 调用 wait 进入唤醒队列的原子性

Thread b需要改写:

1: pthread_mutex_lock(&mutex);
2: ready = true;
3: pthread_mutex_unlock(&mutex);
4: pthread_cond_signal(&cond);

Thread b中2行与3行交换也是可以的:

2: ready = true;
3: pthread_cond_signal(&cond);

现在有一种wait morphing优化,可以减少唤醒-睡眠等待mutex-唤醒的上下文切换。

解锁互斥量mutex和发出唤醒信号condition_signal是两个单独的操作,那么就存在一个顺序的问题。谁先随后可能会产生不同的结果。如下:

(1) 按照 unlock(mutex); condition_signal()顺序, 当等待的线程被唤醒时,因为mutex已经解锁,因此被唤醒的线程很容易就锁住了mutex然后从conditon_wait()中返回了。

(2) 按照 condition_signal(); unlock(mutext)顺序,当等待线程被唤醒时,它试图锁住mutex,但是如果此时mutex还未解锁,则线程又进入睡眠,mutex成功解锁后,此线程在再次被唤醒并锁住mutex,从而从condition_wait()中返回。这种现象称为惊群效应。

按照(2)的顺序,对等待线程可能会发生2次的上下文切换,严重影响性能。因此在后来的实现中,对(2)的情况,如果线程被唤醒但是不能锁住mutex,则线程被转移(morphing)到互斥锁mutex的等待队列中而不是转移到可调度队列争抢cpu时间片,避免了上下文的切换造成的开销。

虚假唤醒(spurious wakeup)

pthread_cond_wait为什么需要使用while循环检查?

因为在多核处理器下,pthread_cond_signal可能会激活多于一个线程(阻塞在条件变量上的线程)。结果是,当一个线程调用pthread_cond_signal()后,多个调用pthread_cond_wait()或pthread_cond_timedwait()的线程返回。

pthread_mutex_lock(&mtx);
while (msg_list.empty()) { //用while而不是ifpthread_cond_wait(&cond, &mtx);
}
msg = msg_list.pop();
pthread_mutex_unlock(&mtx);

调用pthread_cond_broadcast会唤醒所有等待线程,所以也会出现虚拟唤醒情况。

惊群效应

前面讲过的无效唤醒的现象就是惊群效应,就是多进程(多线程)在同时阻塞等待同一个事件的时候(休眠状态),如果等待的这个事件发生,那么他就会唤醒等待的所有进程(或者线程),但是最终却只可能有一个进程(线程)获得这个时间的“控制权”,对该事件进行处理,而其他进程(线程)获取“控制权”失败,只能重新进入休眠状态,造成性能浪费。

具体的惊群现象有具体的解决办法。比如web服务器里面,主线程创建listenfd之后,各个子线程创建并管理各自的epollfd。如果子线程把listenfd加入自己的epollfd,那么新连接到来时就会产生惊群。合理的做法是采用reactor模式,由主线程负责accept(或者放入某一个epollfd),将新连接分发给负载最低的子线程,然后子线程再把connfd加入到epoll中。

同步原语问题汇总--芒果TV进击面试相关推荐

  1. 芒果tv android面试,芒果tv交互岗实习面经以及反思

    先说结果:交互挂了 大二下学期末我一直在找实习,我一直想进芒果tv产品部门但是找到的招聘信息都是其他部门的,然后我选择性的投了一些运营部门.后来通过朋友(爪哥)给我芒果tv产品总监(在此谢谢爪哥)lh ...

  2. 2017湖南卫视跨年晚会新台网互动,大品牌抢占新年头彩尽在芒果TV!

    相较于其它时段的晚会综艺,一年一度的跨年晚会极速聚焦受众且情怀浓郁.出众的第一支广告更能让品牌抢占新年头彩,在万众瞩目的跨年时刻引爆传播,品牌烙印自然深刻入心,这也是跨年晚会内容营销的魅力所在. 作为 ...

  3. 攻克视频AI界难题,直通芒果TV offer,这场算法大赛你一定不能错过

    一场面向顶尖 AI 技术人才的数据竞赛正广募英雄,获奖者不仅有奖金回报,还有机会直接进入芒果 TV 算法岗位面试.首届「马栏山杯」国际音视频算法大赛正在火热进行中. 在当前热门的人工智能领域,就业竞争 ...

  4. Linux同步原语系列-spinlock及其演进优化

    1. 引言 通常我们的说的同步其实有两个层面的意思: 一个是线程间的同步,主要是为了按照编程者指定的特定顺序执行: 另外一个是数据的同步,主要是为了保存数据. 为了高效解决同步问题,前人抽象出同步原语 ...

  5. Win10《芒果TV》更新v3.8.30流星版:优化稳定性、升级无边框播放体验

    随着暑假到来,大波王牌综艺和青春电视剧热浪来袭,Win10版<芒果TV>全平台同步更新流星版v3.8.30,进一步提升稳定性,巩固播放体验,升级剧场模式和画中画无边框体验,我们在芒果等你. ...

  6. 芒果TV“一云多屏”的统一架构图景

    视频市场在刚刚兴起时可以说竞争异常激烈,现如今的视频市场已经几分天下,而芒果TV是其中唯一一家由传统媒体转型而来. 目前芒果TV全网日活跃用户超过4100万,全网日均播放量1.8亿次,App安装激活量 ...

  7. Win10商店芒果TV UWP版更新,新增后台视频下载

    湖南卫视旗下唯一官方视频平台<芒果TV>近日向Win10商店提交了芒果TV UWP V3.0.0版,这次为广大Win10平台用户带来了期待已久的重大功能和更新,可谓是良心厂商,值得鼓励和支 ...

  8. 新版芒果tv电脑版 v6.3.9官方版

    芒果tv新版是湖南卫视新媒体金鹰网旗下的免费网络直播电脑版客户端,在整合湖南广播电视台和芒果传媒优质资源的基础上,大力整合内容.创新服务应用.拓展传播领域.完善用户体验,开辟新型视频传播业态,贯通视频 ...

  9. 超强安利芒果TV for Mac客户端V6.3.7官方版

    今天小编为大家带来了芒果TVMac客户端,芒果tv mac版是湖南广播电视台旗下唯一互联网视频平台,能够让用户在Mac上观看湖南卫视所有电视栏目高清视频点播服务,有需要的朋友快来看看吧! 下载地址:h ...

最新文章

  1. 英伟达联手Arm CPU打造AI超算,百万兆级性能,主攻气候变化和核武建模
  2. 一些C++的开源项目和C++库以及修炼C++的方法
  3. linux进入text目录,Linux文件和目录操作命令 | Soo Smart!
  4. iOS - OC NSSize 尺寸
  5. 上位机多个下位机modbustcp通讯_【C#上位机】西门子1200PLC实用定位控制程序案例...
  6. 【Python基础】13个知识点,系统整理Python时间处理模块Datetime
  7. K8S批量scale deploy的副本为0,结合xargs -I使用
  8. SQL Server 2005 智能感知插件 - SQL Prompt 3.8.0.224
  9. try、catch、finally 和 throw-C#异常处理
  10. 【CCF】201609-2火车购票
  11. python上传文件进度_python实现进度条--主要用在上传下载文件
  12. python写web自动化_jenkins+selenium+python实现web自动化测试
  13. [BX]和loop指令06 - 零基础入门学习汇编语言28
  14. 记忆化搜索:POJ1088-滑雪(经典的记忆化搜索)
  15. 如何把微信朋友圈的小视频转发到自己的朋友圈
  16. 从零开始搭建服务器,拥有一个属于自己的网站
  17. 软件分类(自由软件、开放源代码软件、公共软件......)
  18. 金九银十,测试思维面试题最新整理!
  19. centos查看显卡型号时出现 NVIDIA Corporation
  20. SmartZoneOCR识别控件免费下载地址

热门文章

  1. win10家庭版 edge浏览器自启动怎么关闭
  2. vue.js高仿饿了吗实现tips
  3. 男子“被贷款”2239万背后:放款方华夏银行开年收千万罚单,和平安普惠合作大额助贷产品
  4. dotty编译器语法特性之一枚举类型
  5. feishu-飞书记录
  6. 2048游戏实现,html+css+js
  7. Delphi中捕获音频函数OnWaveIn的使用小记
  8. nginx配置ssl证书流程及常见问题
  9. android 呼吸气泡动画,Android:会呼吸的悬浮气泡
  10. 读《鲁冰逊漂流记》知识归纳思维导图模板