信号量

RT_Thread应用8—信号量2

独自空忆成欢 提交于 2019-12-21 17:55:33
第十九章 信号量(第二部分) 一、信号量控制块 每一个信号量都有自己的信号量控制块,信号量控制块中包含了信号量的所有信息, 1 struct rt_semaphore { 2 struct rt_ipc_object parent ; /**< 继承自 ipc_object 类*/ 3 4 rt_uint16_t value ; /**< 信号量的值,最大为 65535 */ 5 } ; 6 typedef struct rt_semaphore * rt_sem_t ; * * rt_semaphore 对象从 rt_ipc_object 中派生,由 IPC 容器管理。 * * 二、常用信号量函数 信息 二值信号量的最大计数值为 1,并且都是使用 RT-Thread 的同一个释放与获取函数,所以在将信号量当二值信号量使用的时候要注意:用完信号量及时释放,并且不要调用多次信号量释放函数。 1、 信号量创建函数 rt_sem_create() 1 rt_sem_t rt_sem_create ( const char *name, ( 1 ) **信号量名称。 ** 2 rt_uint32_t value, ( 2 ) **可用信号量初始值。 ** 3 rt_uint8_t flag ) ( 3 ) **信号量标志。** 4 { 5 rt_sem_t sem ; 6 7 RT

并发和多线程

旧街凉风 提交于 2019-12-21 07:08:59
并发(concurrency):某段时间内,多个任务被CPU交替处理。 并行(parallelism):CPU同时处理多个任务。 并发打破和程序的封闭性,具有以下挑战: 1、并发程序之间有相互制约(对资源的争抢和彼此的依赖)的关系。 2、并发线程执行过程不连贯、断断续续,需要保存和切换现场。 3、设计合理的并发数,充分并合理利用CPU的执行能力才能真正发挥并发的优势。 线程数量并不是越多越好,要和相应的CPU资源匹配,合适的线程数才能充分利用计算资源。 线程的五个状态:NEW新建状态、RUNNABLE就绪状态、RUNNING运行状态、BLOCKED阻塞状态、DEAD终止状态。 线程被创建且未启动时的状态为NEW;线程调用start()方法之后进入就绪状态为RUNNABLE;线程被分配CPU时间片,开始执行run()方法,线程进入执行状态RUNNING;线程由于某些原因会进入阻塞状态BLOCKED;线程执行完毕,退出run()方法或异常退出即进入终止态DEAD。 有三类原因会让RUNNING中的线程变成BLOCKED:等待阻塞(调用wait方法)、主动阻塞(通过sleep、join主动让出CPU执行权)、同步阻塞(需要等待其他线程释放锁,I/O阻塞、同步块阻塞、锁阻塞) 线程从BLOCKED状态通过“苏醒(sleep时间到了)”、“被唤醒(notify)”、“获得锁

[linux] 进程间通讯的几种方式

蓝咒 提交于 2019-12-21 02:51:05
linux进程间通信(IPC)有几种方式,下面将将简单的简述一下:   一。管道(pipe)   管道是Linux支持的最初IPC方式,管道可分为无名管道,有名管道等。   (一)无名管道,它具有几个特点:   1) 管道是半双工的,只能支持数据的单向流动;两进程间需要通信时需要建立起两个管道;   2) 无名管道使用pipe()函数创建,只能用于父子进程或者兄弟进程之间;   3) 管道对于通信的两端进程而言,实质上是一种独立的文件,只存在于内存中;   4) 数据的读写操作:一个进程向管道中写数据,所写的数据添加在管道缓冲区的尾部;另一个进程在管道中缓冲区的头部读数据。   (二)有名管道   有名管道也是半双工的,不过它允许没有亲缘关系的进程间进行通信。具体点说就是,有名管道提供了一个路径名与之进行关联,以FIFO(先进先出)的形式存在于文件系统中。这样即使是不相干的进程也可以通过FIFO相互通信,只要他们能访问已经提供的路径。   值得注意的是,只有在管道有读端时,往管道中写数据才有意义。否则,向管道写数据的进程会接收到内核发出来的SIGPIPE信号;应用程序可以自定义该信号处理函数,或者直接忽略该信号。   二。信号量(semophore)   信号量是一种计数器,可以控制进程间多个线程或者多个进程对资源的同步访问,它常实现为一种锁机制。实质上,信号量是一个被保护的变量

C#多线程编程

回眸只為那壹抹淺笑 提交于 2019-12-20 07:58:02
C#多线程编程 一、使用线程的理由 1、可以使用线程将代码同其他代码隔离,提高应用程序的可靠性。 2、可以使用线程来简化编码。 3、可以使用线程来实现并发执行。 二、基本知识 1、进程与线程:进程作为操作系统执行程序的基本单位,拥有应用程序的资源,进程包含线程,进程的资源被线程共享,线程不拥有资源。 2、前台线程和后台线程:通过Thread类新建线程默认为前台线程。当所有前台线程关闭时,所有的后台线程也会被直接终止,不会抛出异常。 3、挂起(Suspend)和唤醒(Resume):由于线程的执行顺序和程序的执行情况不可预知,所以使用挂起和唤醒容易发生死锁的情况,在实际应用中应该尽量少用。 4、阻塞线程:Join,阻塞调用线程,直到该线程终止。 5、终止线程:Abort:抛出 ThreadAbortException 异常让线程终止,终止后的线程不可唤醒。Interrupt:抛出 ThreadInterruptException 异常让线程终止,通过捕获异常可以继续执行。 6、线程优先级:AboveNormal BelowNormal Highest Lowest Normal,默认为Normal。 三、线程的使用 线程函数通过委托传递,可以不带参数,也可以带参数(只能有一个参数),可以用一个类或结构体封装参数。 namespace Test { class Program {

自旋锁+信号量

 ̄綄美尐妖づ 提交于 2019-12-20 04:19:30
本文将为你介绍内核同步算法中的自旋锁和信号量。在这之前,先了解一些概念。 执行线程:thread of execution,指任何正在执行的代码实例,可能是一个正在内核线程,一个中断处理程序等。有时候会将执行线程简称为线程。 临界区:critical region,即访问和操作共享数据的代码段。 多个执行线程并发访问同一资源通常是不安全的,通常使用自旋锁和信号量来实现对临界区互斥的访问。 自旋锁 自旋锁(spin lock)是一个对临界资源进行互斥访问的典型手段。自旋锁至多只能被一个执行线程持有。当一个执行线程想要获得一个已被使用的自旋锁时,该线程就会一直进行忙等待直至该锁被释放,就如同“自旋”所表达的意思那样:在原地打转。 我们也可以这么理解自旋锁:它如同一把门锁,而临界区就如同门后面的房间。当一个线程A进入房间后,它会关闭房门,使得其他线程不得进入。此时如果其他某个进程B需要进入房间,那么只能在门外“打转”。当A进程打开们后,进程B才能进入房间。 自旋锁的使用 1.定义初始化自旋锁 使用下面的语句就可以先定一个自旋锁变量,再对其进行初始化: 1 spinlock_t lock; 2 spin_lock_init(&lock); 也可以这样初始化一个自旋锁: 1 spinlock_t lock=SPIN_LOCK_UNLOCKED; 2.获得自旋锁 1 void spin

(笔记)Linux内核学习(七)之内核同步机制和实现方式

好久不见. 提交于 2019-12-19 22:43:10
一 原子操作 指令以原子的方式执行——执行过程不被打断。 1 原子整数操作 原子操作函数接收的操作数类型——atomic_t //定义 atomic_t v;//初始化 atomic_t u = ATOMIC_INIT(0); //操作 atomic_set(&v,4); // v = 4 atomic_add(2,&v); // v = v + 2 = 6 atomic_inc(&v); // v = v + 1 = 7 //实现原子操作函数实现 static inline void atomic_add(int i, atomic_t *v) { unsigned long tmp; int result; __asm__ __volatile__("@ atomic_add\n"     "1: ldrex %0, [%3]\n"     " add %0, %0, %4\n"     " strex %1, %0, [%3]\n"     " teq %1, #0\n"     " bne 1b"   : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)   : "r" (&v->counter), "Ir" (i)   : "cc"); } 2 原子位操作 //定义 unsigned long word = 0; //操作

iOS开发之用到的几种锁整理

*爱你&永不变心* 提交于 2019-12-19 16:36:09
1. iOS中的互斥锁 在编程中,引入对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问对象。 1.1 @synchronized (self) - (void)lock1 { @synchronized (self) { // 加锁操作 }} 1.2 NSLock - (void)lock2 { NSLock *xwlock = [[NSLock alloc] init]; XWLogBlock logBlock = ^ (NSArray *array) { [xwlock lock]; for (id obj in array) { NSLog(@"%@",obj); } [xwlock unlock]; }; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSArray *array = @[@1,@2,@3]; logBlock(array); });} 1.3 pthread pthread除了创建互斥锁,还可以创建递归锁、读写锁、once等锁 __block pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL);

Java中的线程

泄露秘密 提交于 2019-12-19 03:09:54
我们可以在计算机上运行各种计算机软件程序。每一个运行的程序可能包括多个独立运行的线程(Thread)。 线程(Thread)是一份独立运行的程序,有自己专用的运行栈。线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等。 当多个线程同时读写同一份共享资源的时候,可能会引起冲突。这时候,我们需要引入线程“同步”机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团。 同步这个词是从英文synchronize(使同时发生)翻译过来的。我也不明白为什么要用这个很容易引起误解的词。既然大家都这么用,咱们也就只好这么将就。 线程同步的真实意思和字面意思恰好相反。线程同步的真实意思,其实是“排队”:几个线程之间要排队,一个一个对共享资源进行操作,而不是同时进行操作。 因此,关于线程同步,需要牢牢记住的第一点是:线程同步就是线程排队。同步就是排队。线程同步的目的就是避免线程“同步”执行。这可真是个无聊的绕口令。 关于线程同步,需要牢牢记住的第二点是 “共享”这两个字。只有共享资源的读写访问才需要同步。如果不是共享资源,那么就根本没有同步的必要。 关于线程同步,需要牢牢记住的第三点是,只有“变量”才需要同步访问。如果共享的资源是固定不变的,那么就相当于“常量”,线程同时读取常量也不需要同步。至少一个线程修改共享资源,这样的情况下,线程之间就需要同步。 关于线程同步

Qt实现环形缓冲区

喜夏-厌秋 提交于 2019-12-18 09:51:59
首先认识一个类QSemaphore QSemaphore 他提供了一个通用的计数信号量,信号量是互斥量的泛化。虽然互斥锁只能被锁定一次,但是可以获得一个信号量多次。信号量通常用于保护一定数量的相同资源。信号量支持两个基本操作,acquire()和release(): acquire(n) 获取n个资源。如果没有那么多可用资源,调用将阻塞; release(n)释放n个资源。 实现方式: #include "widget.h" #include "ui_widget.h" #include <QSemaphore> #include <QQueue> QSemaphore freeBytes(100); //初始化缓冲区大小 缓冲器的未用量 QSemaphore usedBytes(0); //缓冲区的已用量 QQueue<QString> timeQueue; //缓冲区 Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); timer = new QTimer(this); connect(timer,SIGNAL(timeout()),this,SLOT(Write())); timer->start(1000); star(); } Widget::

进程通信-- 信号量

不问归期 提交于 2019-12-18 05:33:10
1,信号量定义 关键字:共享资源,P,V操作 信号量是一个特殊的变量,程序对其访问都是原子操作,且只允许对它进行等待(即P(信号变量))和发送(即V(信号变量))信息操作 P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行 V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1. 创建一个新信号量或取得一个已有信号量 int semget ( key_t key, int num_sems, int sem_flags); 第一个参数key是整数值(唯一非零),不相关的进程可以通过它访问一个信号量,它代表程序可能要使用的某个资源,程序对所有信号量的访问都是间接的,程序先通过调用semget函数并提供一个键,再由系统生成一个相应的信号标识符(semget函数的返回值),只有semget函数才直接使用信号量键,所有其他的信号量函数使用由semget函数返回的信号量标识符。如果多个程序使用相同的key值,key将负责协调工作。 第二个参数num_sems指定需要的信号量数目,它的值几乎总是1。 第三个参数sem_flags是一组标志,当想要当信号量不存在时创建一个新的信号量,可以和值IPC_CREAT做按位或操作。设置了IPC_CREAT标志后,即使给出的键是一个已有信号量的键,也不会产生错误。而IPC