RT-Thread的线程间同步

禁止系统调度
上一节《 多线程导致的临界区问题》中由于 test1 线程被 test2 线程打断,才导致了我们没有得到预期的结果,我们一般可通过关闭中断和调度器上锁这两种简单的途径来禁止系统调度,防止线程被打断,从而保证临界区不被破坏。

1、 关闭中断
线程中关闭中断保护临界区的结构如下:

#include <rtthread.h>
#include <stm32f10x.h>
#include "test.h"

rt_uint32_t  g_tmp;/* 定义一个全局变量*/

/*  变量分配4字节对齐 */
ALIGN(RT_ALIGN_SIZE)

/*  静态线程的 线程堆栈*/
static rt_uint8_t thread1_stack[512];
static rt_uint8_t thread2_stack[512];

/* 静态线程的 线程控制块 */
static struct rt_thread thread_test1;
static struct rt_thread thread_test2;

static void test1_thread_entry(void* parameter);
static void test2_thread_entry(void* parameter);

void demo_thread_creat(void)
{
    rt_err_t result;

    /* 创建静态线程 : 优先级 16 ,时间片 2个系统滴答 */
    result = rt_thread_init(&thread_test1,
                            "test1",
                            test1_thread_entry, RT_NULL,
                            (rt_uint8_t*)&thread1_stack[0], sizeof(thread1_stack), 16, 2);

    if (result == RT_EOK)
    {
        rt_thread_startup(&thread_test1);
    }

    /* 创建静态线程 : 优先级 15 ,时间片 1个系统滴答 */
    result = rt_thread_init(&thread_test2,
                            "test2",
                            test2_thread_entry, RT_NULL,
                            (rt_uint8_t*)&thread2_stack[0], sizeof(thread2_stack), 15, 1);

    if (result == RT_EOK)
    {
        rt_thread_startup(&thread_test2);
    }

}

void test1_thread_entry(void* parameter)
{
    rt_uint32_t i;

    /* 调度器上锁,上锁后,将不再切换到其他线程,仅响应中断 */
    rt_enter_critical();

    g_tmp = 0;
    rt_kprintf("g_tmp=:%d \r\n", g_tmp);
    for(i=0; i<10000; i++)
    {
        g_tmp++;
    }
    rt_kprintf("g_tmp=:%d \r\n", g_tmp);

    /* 调度器解锁 */
    rt_exit_critical();
}

void test2_thread_entry(void* parameter)
{
    rt_thread_delay(1);// 1
    g_tmp++;
}

把调度器锁住也能让当前运行的任务不被换出,直到调度器解锁。但和关闭中断有一点不相同的是,对调度器上锁,系统依然能响应外部中断,中断服务例程依然有可能被运行。
所以在使用调度器上锁的方式来做任务同步时,需要考虑好, 任务访问的临界资源是否会被中断服务例程所修改,如果可能会被修改,那么将不适合采用此种方式作为同步的方法。

PS: 上面两种方法的的宗旨其实就是:在临界区内只允许一个线程运行!

除了禁止调度器调度,我们还用线程间通信的方式来保证线程间的同步, 下面我们来介绍 RT-Thread 中的 IPC 对象:信号量、互斥锁、事件、消息队列、邮箱。

时间: 2024-10-13 06:35:00

RT-Thread的线程间同步的相关文章

Linux进程间通信与线程间同步详解(全面详细)

引用:http://community.csdn.net/Expert/TopicView3.asp?id=4374496linux下进程间通信的几种主要手段简介: 1. 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信:   2. 信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身

Java并发:线程间同步-条件队列和同步工具类

转载请注明出处: jiq?钦's technical Blog - 季义钦 线程之间的同步,除了互斥(前面介绍的互斥锁)之外,还存在协作关系,下面我们就介绍一下java线程间常见的一些协作方式. 一.内置条件队列 正如每个Java对象都可以作为一个内置锁,每个对象也可以作为一个条件队列,称为内置条件队列,Object.wait().notify()/notifyAll()构成了内置条件队列的API. 需要注意的是,调用任何对象X的内置条件队列的API都必须要先获得该对象X的内置锁. 1.API介

线程间同步之信号量实现环形buf

一.概述: 信号量是一个非负整数的计数器,它通过计数器来实现多线程对临界资源的顺序访问,从而实现线程间的同步.它与进程间通信的信号量不同,进程间通信的信号量是一个信号量集,而线程间同步的信号量是一个信号.还有一点,就是对信号量的操作是原子的. 信号量与互斥锁的区别: (1).互斥锁的值只能是0或1,而信号量的值为非负整数. (2).互斥锁用与实现线程间的互斥,而信号量用于实现线程间的同步. (3).互斥锁的加锁和解锁必须由同一个线程分别对应使用,而信号量可以由一个线程得到,另一个线程释放. 下面

conditon_variable(条件变量)用于线程间同步

conditon_variable(条件变量)用于线程间同步 condition_variable有5个函数,函数名及对应的功能如下: wait阻塞自己,等待唤醒 wait_for阻塞自己,等待唤醒,最多等待一段时间 wait_until阻塞自己,等待唤醒,最多等待到某个时间点 notify_one 唤醒一个等待在这个条件变量上的线程 notify_all 唤醒所有等待在这个条件变量上的线程 3个wait函数都要求输入一个已经上锁的unique_lock<mutex>变量,并且都有两个版本,一

linux线程间同步方式汇总

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

rtt学习之线程间同步与通信

一 线程间的同步与互斥:信号量.互斥量.实践集 线程互斥是指对于临界区资源访问的排它性,如多个线程对共享内存资源的访问,生产消费型对产品的操作.临界区操作操作方法有: rt_hw_interrupt_disable() / rt_enter_critical()进入临界区, rt_hw_interrupt_enable() / rt_exit_critical()退出临界区 信号量的创建:rt_sem_t rt_sem_create(const char *name,rt_uint32_t va

android 线程间同步问题

我现在有2个android线程,一个是view 线程,一个是工作线程,我现在想让 工程线程暂停,直到view线程的 onDraw方法被调用后再继续运行 如何做?如何等待信号 处理方法 在java2个线程中传递对象,让一个线程去通知另一个线程的方式如下,在工作线程中调用 stick.wait(); When the view thread finishes its onDraw work, it calls this: 当view线程调用完onDraw的时候可以调用 stick.notify();

【C#】SynchronizationContext线程间同步

SynchronizationContext在通讯中充当传输者的角色,实现功能就是一个线程和另外一个线程的通讯. 需要注意的是,不是每个线程都附加SynchronizationContext这个对象,只有UI线程是一直拥有的.故获取SynchronizationContext也只能在UI线程上进行SynchronizationContext context = SynchronizationContext.Current; 那什么时候会用到呢? 在多线程操作时往往需要切回某个线程中去工作,等完成

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

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