互斥锁

生产者-消费者设计模式

▼魔方 西西 提交于 2019-12-10 03:02:59
一、生产者消费者设计模式 1、中间队列 一段内存空间,且可存取; 2、两种角色 (1)生产者:生产数据; (2)消费者:消费数据。 3、三种关系 (1)生产者与生产者的互斥关系; (2)消费者与消费者的互斥关系; (3)生产者与消费者的互斥且同步关系。 二、实现方式 1、使用synchronized(wait()和notify()) 2、使用Lock实现(await()和signal()) 3、阻塞队列实现 三、生产者-消费者模型的优点 1、解耦:降低生产者和消费之间的依赖关系 2、支持并发 即生产者和消费者是两个可以独立的并发主体,互不干扰的运行,如果没有中间的环节,则会生产者阻塞或者消费者阻塞。不管是哪种方法效率都比较低。 3、支持盲闲不均 如果生产数据的速度时快时慢,缓冲区可以对其进行适当缓冲。当生产的数据太块时,消费者来不及处理,未处理的数据可以暂时存在缓冲区。等生产者的生产速度慢下来,消费者再慢慢处理掉。 四、提升与思考 1、队列可以有多种实现: (1)先放先出:FIFO (2)后放先出:LIFO (3)优先级队列:Priority Queue 2、为什么生产和消费要用多线程 单线程太耗时,只有当多线程的效率提升可以抵消开发难度和性能消耗时才有必要用多线程; 3、别忘记sychronized和notifyAll() 否则其他线程一直等待,不会继续 4

多线程锁

烈酒焚心 提交于 2019-12-10 02:18:07
1、互斥锁: Mutex属于sleep-waiting类型的锁 。例如在一个双核的机器上有两个线程(线程A和线程B),它们分别运行在Core0和Core1上。假设线程A想要通过pthread_mutex_lock操作去得到一个临界区的锁,而此时这个锁正被线程B所持有,那么线程A就会被阻塞,Core0会在此时进行上下文切换(Context Switch)将线程A置于等待队列中,此时Core0就可以运行其它的任务而不必进行忙等待。 2、 自旋锁(Spin lock) 自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,“自旋锁”的作用 是为了解决某项资源的互斥使用。因为自旋锁不会引起调用者睡眠,所以自旋锁的效率远高于互斥锁。 自旋锁的不足之处 : 自旋锁一直占用着CPU,他在未获得锁的情况下,一直运行(自旋),所以占用着CPU,如果不能在很短的时间内获得锁,这无疑会使CPU效率降低。 在用自旋锁时有可能造成死锁,当递归调用时有可能造成死锁,调用有些其他函数也可能造成死锁,如 copy_to_user()、copy_from_user()、kmalloc()等。 因此我们要慎重使用自旋锁,自旋锁只有在内核可抢占式或SMP的情况下才真正需要,在单CPU且不可抢占式的内核下,自旋锁的操作为空操作。

进程间、线程间通信方式

偶尔善良 提交于 2019-12-09 20:14:19
一、进程间的通信方式 (1)管道( pipe ) :管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。 (2)有名管道 (namedpipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。 (3) 信号量(semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。 (4) 消息队列( messagequeue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。 (5) 信号 (sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。 (6) 共享内存(shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。 (7) 套接字(socket ) : 套解口也是一种进程间通信机制

myql的锁

早过忘川 提交于 2019-12-06 08:20:48
本文主要涉及以下几个个部分: 1. 为什么要加锁 2. 锁的分类 3. 常见语句的加锁分析 4. 如何分析死锁 5. 如何预防死锁 先列出本地的运行环境 数据库版本是5.7,隔离级别是Repeatable-Read(可重复读),不同的数据库版本和隔离级别对语句的执行结果影响很大。所以需要说明版本和隔离级别 一、为什么要加锁 数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中加锁是为了保证数据库的一致性。 数据库有ACID原则,其中I是隔离性, 脏读:读未提交的数据 不可重复读:读已修改的数据 虚读:读提交了插入/删除的数据 事务隔离机制 和标准SQL规范相比,MySQL中可重复读解决了幻读,实现了串行化隔离级别的功能,同时没有严重影响并发。是通过加锁、阻止插入新数据,来解决幻读的。 二、锁的分类 锁 我们听说过读锁、写锁、共享锁、互斥锁、行锁等等各种名词,简单对这些锁进行了分类。 锁的分类 加锁机制: 1、乐观锁:先修改,保存时判断是够被更新过,应用级别 2、悲观锁:先获取锁,再操作修改,数据库级别 锁粒度: 表级锁:开销小,加锁快,粒度大,锁冲突概率大,并发度低,适用于读多写少的情况。 页级锁:BDB存储引擎 行级锁:Innodb存储引擎,默认选项 兼容性: S锁,也叫做读锁、共享锁,对应于我们常用的 select * from users where id

Go 语言入门(三)并发

筅森魡賤 提交于 2019-12-06 06:56:06
写在前面 在学习 Go 语言之前,我自己是有一定的 Java 和 C++ 基础的,这篇文章主要是基于 A tour of Go 编写的,主要是希望记录一下自己的学习历程,加深自己的理解 Go 语言入门(三)并发 Go 程 「Go 程」 goroutine :由 Go 运行时管理的 轻量级线程 。 运行「Go 程」很简单,只要执行下面代码: go f(x, y, z) 就会启动一个新的 Go 程并执行 f(x, y, z) 。 f 、 x 、 y 和 z 的运算发生在当前的 Go 程中,而 f 的执行发生在新的 Go 程中。 「Go 程」 在相同的地址空间中运行 ,因此 在访问共享的内存时必须进行同步 。 sync 包提供了这种能力,不过在 Go 中并不经常用到,我们用得比较多的是 信道 。 信道 「信道」是 带有类型的管道 ,你可以通过它用信道操作符 <- 来发送或者接收值: ch <- v // 将 v 发送至信道 ch v := <-ch // 从信道 ch 接受值并赋予 v 可以看到,操作符 <- 是一个箭头,实际上就是表示数据的流向。它有些类似于队列,对于发送至信道的值是 先进先出 的。 使用信道 和「切片」以及「映射」一样,在使用信道之前,我们必须先初始化一个信道: ch := make(chan int) 默认情况下, 发送和接收操作在另一端准备好之前都会阻塞 。这使得

linux中c多线程同步方法

我只是一个虾纸丫 提交于 2019-12-06 02:53:54
https://blog.csdn.net/jkx01whg/article/details/78119189 Linux下提供了多种方式来处理线程同步,最常用的是互斥锁、条件变量和信号量。 一、互斥锁(mutex)   锁机制是同一时刻只允许一个线程执行一个关键部分的代码。 1. 初始化锁   int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr); 其中参数 mutexattr 用于指定锁的属性(见下),如果为NULL则使用缺省属性。 互斥锁的属性在创建锁的时候指定,在LinuxThreads实现中仅有一个锁类型属性,不同的锁类型在试图对一个已经被锁定的互斥锁加锁时表现不同。当前有四个值可供选择: (1)PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。 (2)PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。 (3)PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁

自旋锁、互斥锁

≯℡__Kan透↙ 提交于 2019-12-05 23:05:55
自旋锁(spinlock):是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。 它是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,”自旋”一词就是因此而得名。 来源: https://www.cnblogs.com/macht/p/11949609.html

python线程事件Event(30)

╄→гoц情女王★ 提交于 2019-12-05 19:41:10
在python项目开发中,线程thread使用是比较常见的,在前面的文章中我们介绍了 python线程的创建 以及 线程互斥锁 ,今天还要额外介绍一个与线程相关的内容 – 事件Event。 一.python事件Event相关函数介绍 set() — 全局内置标志Flag,将标志Flag 设置为 True,通知在等待状态(wait)的线程恢复运行; isSet() — 获取标志Flag当前状态,返回True 或者 False; wait() — 一旦调用,线程将会处于阻塞状态,直到等待其他线程调用set()函数恢复运行; clear() — 将标志设置为False; 二.python事件Event原理 事件event中有一个全局内置标志Flag,值为 True 或者False。使用wait()函数的线程会处于阻塞状态,此时Flag指为False,直到有其他线程调用set()函数让全局标志Flag置为True,其阻塞的线程立刻恢复运行,还可以用isSet()函数检查当前的Flag状态. 三.python事件Event使用 假如有这样一个场景:有10个单身狗,对面100米有10个美女,同时起跑,一人一个,自由选择,先到先得….. # !usr/bin/env python # -*- coding:utf-8 _*- """ @Author:何以解忧 @Blog(个人博客地址):

STM32F104ZET6之ucosⅢ常用函数

跟風遠走 提交于 2019-12-05 19:23:49
一、OS的初始化与启动 1.OS初始化,初始化各种内核对象和全局变量 函数原型:void OSInit (OS_ERR *p_err) 参数:p_err,用于返回错误码 返回值:无 它是第一个执行的函数。 2.启动OS,创建任务后调用 函数原型:void OSStart (OS_ERR *p_err) 参数:p_err,用于返回错误码 返回值:无 二、任务的管理 1.创建任务 void OSTaskCreate (OS_TCB *p_tcb,//类似于线程id,控制任务 CPU_CHAR *p_name,//任务的名字,可以自定义 OS_TASK_PTR p_task,//任务函数,类似线程函数 void *p_arg,//任务传递参数,类似于给线程函数传递参数 OS_PRIO prio,//任务的优先级 CPU_STK *p_stk_base,//任务栈基址,提供一个数组基址(任务栈数组基地址) CPU_STK_SIZE stk_limit,//空出10%的栈空间给到堆栈检测函数使用,反过来说,当前任务只能使用90%栈空间 CPU_STK_SIZE stk_size,//任务栈的大小,以字(32位)为单位 OS_MSG_QTY q_size,//任务内消息队列的大小,若不使用,写0 OS_TICK time_quanta,//时间片轮转调度算法,若不使用,写0(这是时间片的长度)

各类锁(互斥锁,自旋锁,读写锁,乐观锁,悲观锁,死锁)

拜拜、爱过 提交于 2019-12-05 19:06:08
互斥锁 当有一个线程要访问共享资源(临界资源)之前会对线程访问的这段代码(临界区)进行加锁。如果在加锁之后没释放锁之前其他线程要对临界资源进行访问,则这些线程会被阻塞睡眠,直到解锁,如果解锁时有一个或者多个线程阻塞,那么这些锁上的线程就会变成就绪状态,然后第一个变为就绪状态的线程就会获取资源的使用权,并且再次加锁,其他线程继续阻塞等待。 读写锁 也叫做共享互斥锁,读模式共享,写模式互斥。有点像数据库负载均衡的读写分离模式。它有三种模式:读加锁状态,写加锁状态和不加锁状态。简单来说就是只有一个线程可以占有写模式的读写锁,但是可以有多个线程占用读模式的读写锁。 当写加锁的模式下,任何线程对其进行加锁操作都会被阻塞,直到解锁。 当在读加锁的模式下,任何线程都可以对其进行读加锁的操作,但所有试图进行写加锁操作的线程都会被阻塞。直到所有读线程解锁。但是当读线程太多时,写线程一直被阻塞显然是不对的,所以一个线程想要对其进行写加锁时,就会阻塞读加锁,先让写加锁线程加锁 自旋锁 自旋锁和互斥锁很像,唯一不同的是自旋锁访问加锁资源时,会一直循环的查看是否释放锁。这样要比互斥锁效率高很多,但是只会占用CPU。所以自旋锁适用于多核的CPU。但是还有一个问题是当自旋锁递归调用的时候会造成死锁现象。所以慎重使用自旋锁。 乐观锁 这其实是一种思想,当线程去拿数据的时候,认为别的线程不会修改数据,就不上锁