
嵌入式——线程同步
嵌入式
小C菜鸟
一蓑烟雨任平生
展开
-
7-5 无饿死互斥
参考https://blog.youkuaiyun.com/booksyhay/article/details/82769005在如图中所示的程序中,while语句是一个无限循环; 换句话说,一旦线程离开临界区,它就会循环到顶部并尝试再次获取互斥锁。想象一下,线程A获取互斥锁,线程B和C等待。 当A离开时,B进入,但在B离开之前,A循环回来加入到队列中和C一起排队. B离开时,无法保证C接下来会执行。 ...原创 2020-01-17 16:04:02 · 364 阅读 · 0 评论 -
7-4 写者优先的读者
参考https://blog.youkuaiyun.com/booksyhay/article/details/82762278根据应用程序,为写者提供更高的优先级可能是个好主意。 例如,如果写者要对数据结构进行更新,而这种更新又是时序要求很严格的,则最好在写者有机会继续之前,将能查看旧数据的读者的数量控制到最小。初始化osSemaphoreId_t sem_noReaders;sem_noRead...原创 2020-01-16 19:30:19 · 280 阅读 · 0 评论 -
7-3 读者写者饿死问题
参考https://blog.youkuaiyun.com/booksyhay/article/details/82762278在之前的解决方案中,会存在一个问题: 作者可能会饿死。如果写者到达的时候,临界区中有读者,那么当读者来来往往时,它可能会在队列中等待。只要新读者在最后一位读者离开之前到达,房间里总会有至少一位读者。这种情况不是僵局,因为一些线程正在取得进展,但这并不是完全可取的。只要系统上的负...原创 2020-01-16 19:29:47 · 1664 阅读 · 0 评论 -
7-2 读者写者解决方案封装
与此读者代码类似的模式很常见:进入某个部分的第一个线程锁定信号量(或队列),最后一个线程解锁它。 事实上,它是如此常见,我们应该给它一个名称,并将其包装在一个对象中。模式的名称是Lightswitch,类似于进入房间的第一个人打开灯(锁定互斥锁)的模式,最后一个人将其关闭(解锁互斥锁)。 这是Lightswitch的类定义:typedef struct _LightSwitch{ int...原创 2020-01-14 19:51:27 · 208 阅读 · 0 评论 -
7-1读者写者问题
参考https://blog.youkuaiyun.com/booksyhay/article/details/82762278概念描述:在一些程序中存在读者写者问题,也就是说,对某些资源的访问会 存在两种可能的情况,一种是访问必须是排它行的,就是独占的意思,这称作写操作;另一种情况就是访问方式可以是共享的,就是说可以有多个线程同时去访问某个资源,这种就称作读操作。这个问题模型是从对文件的读写操作中引申...原创 2020-01-14 19:30:29 · 357 阅读 · 0 评论 -
6-2 有限缓冲区的生产者
参考https://blog.youkuaiyun.com/booksyhay/article/details/82743623在6-1中的生产者方案中:尽管这种解决方案是正确的,但仍有机会对其性能进行一次小改进。 想象一下,当生产者发出信号时,至少有一个消费者在队列中。 如果调度程序允许消费者运行,接下来会发生什么? 它会立即阻塞生产者(仍然)持有的互斥锁。阻塞和唤醒是中等昂贵的操作; 不必要地执行...原创 2020-01-13 20:20:54 · 382 阅读 · 0 评论 -
6-1 生产者-消费者问题
在多线程程序中,线程之间通常存在分工。 在一种常见模式中,一些线程是生产者,一些是消费者。需要强制执行几个同步约束才能使此系统正常工作:在缓冲区中添加或删除项目时,缓冲区处于不一致状态。 因此,线程必须具有对缓冲区的独占访问权限。如果消费者线程在缓冲区为空时到达,则会阻塞,直到生产者添加新项目为止。初始化mutex提供对缓冲区的独占访问。 当items为正数时,它表示缓冲区中项目的数量...原创 2020-01-11 17:08:20 · 242 阅读 · 0 评论 -
5 独占队列(Exclusive queue solution)
参考 https://blog.youkuaiyun.com/booksyhay/article/details/82696779信号量也可用于表示队列。在这种情况下,初始值为0,并且通常编写代码以确保不会发出信号,除非有线程在等待。因此信号量的值永远不会为正数。例如,假设线程代表舞厅舞者,并且有两种舞者:领舞(leaders)和伴舞(followers),在进入舞池之前排队等候。 当领舞到达时,它会检查...原创 2020-01-11 15:48:18 · 762 阅读 · 0 评论 -
4-3 预装旋转栅门(Preloaded turnstile)
旋转栅门的一个好处是,它是一个多功能组件,可以用于各种解决方案。 但是一个缺点是它迫使线程顺序执行,这可能导致更多的不必要的上下文切换。在可重复使用的屏障解决方案中,如果解锁旋转栅门的线程预先加载旋转栅门,并且有足够的信号让正确数量的线程通过,就可以简化解决方案。初始化osSemaphoreId_t sem_mutex;sem_mutex = osSemaphoreNew(1, 1, N...原创 2020-01-11 14:46:35 · 432 阅读 · 0 评论 -
4-2 可重复使用屏障(Reusable barrier)
通常,一组协作线程将在循环中执行一系列步骤,完成每个步骤之后在屏障处同步。 对于这个应用程序,我们需要一个可重复使用的屏障,在所有线程通过后锁定自身。为了解决这个问题,我们可以使用两个旋转栅门。最初第一个被锁定,第二个被打开。当所有线程到达第一个时,我们锁定第二个并解锁第一个。当所有线程到达第二个时,我们重新锁定第一个,这使得线程可以安全地循环到开头,然后打开第二个。此解决方案有时被称为...原创 2020-01-11 14:24:49 · 451 阅读 · 0 评论 -
4-1 屏障(Barrier)
第3讲中的会合,只适合于两个线程之间,如果多个线程就不合适;进一步推广会合解决方案。 每个线程都应该运行以下代码:屏障的概念:屏障是多线程各自做自己的工作,如果某一线程完成了工作,就等待在屏障那里,直到其他线程的工作都完成了,再一起做别的事;举个通俗的例子:在百米赛跑里,比赛没开始之前,每个运动员都在赛场上自由活动,有的热身,有的喝水,有的跟教练谈论。比赛快开始时,准备完毕的运动员就预备在起...原创 2020-01-10 20:13:16 · 1371 阅读 · 1 评论 -
3 互斥锁
互斥锁的初始值为1;通过互斥锁保护临界区的代码执行;1、初始化osSemaphoreId_t sem_mutex;int count = 0;2、线程1osSemaphoreAcquire(sem_mutex, osWaitForever);count++;printf("%d\r\n", count);osSemaphoreRelease(sem_mutex);3、线程...原创 2020-01-10 19:11:23 · 283 阅读 · 0 评论 -
2 会合(Rendezvous)
通过两个初始值为0的信号量,会合两个线程;使两个线程都到达集合点,才会进入下面的操作;实现a1在b2之前执行,b1在a2之前执行;1、信号量初始化osSemaphoreId_t sem_a_arrived;osSemaphoreId_t sem_b_arrived;sem_a_arrived = osSemaphoreNew(1, 0, NULL);sem_b_arrived = o...原创 2020-01-10 18:30:33 · 457 阅读 · 0 评论 -
1 同步
参考https://blog.youkuaiyun.com/booksyhay/article/details/82696779通过初始化为0值的信号量,同步两个线程;1、信号量初始化osSemaphoreId_t sem;sem = osSemaphoreNew(1, 0, NULL);2、线程1printf("thread 1\r\n");osSemaphoreRelease(sem);...原创 2020-01-10 18:16:13 · 260 阅读 · 0 评论