包河网站建设,凡科网站投票排行榜是怎么做的,用vs做网站教程,辽阳网站建设多少钱这里写目录标题 同步概念线程同步概念数据混乱原因 互斥量原理锁的注意事项1、cpu时间轮片2、建议锁总结 使用锁来管理线程同步问题产生主要函数init、destorylock、unlock代码注意事项#xff08;锁的粒度#xff09; try锁死锁出现原因图解 读写锁特性图解函数总览init、de… 这里写目录标题 同步概念线程同步概念数据混乱原因 互斥量原理锁的注意事项1、cpu时间轮片2、建议锁总结 使用锁来管理线程同步问题产生主要函数init、destorylock、unlock代码注意事项锁的粒度 try锁死锁出现原因图解 读写锁特性图解函数总览init、destroyrdlock、tryrdlockwrlock、trywrlockunlock 代码 条件变量二级目录二级目录二级目录 信号量二级目录二级目录二级目录 同步概念
线程同步概念 数据混乱原因 互斥量
原理 多个线程操作共享区时每个线程访问时会加上一把锁只允许某单个线程对共享区进行操作操作完之后再解锁表示允许其他线程访问
而这个锁就叫互斥锁这个互斥锁只有一把各个线程争抢这把锁谁先拿到锁谁先有操作共享区的权利
锁的注意事项
1、cpu时间轮片 当线程T1执行写入0的操作的过程中T1的cpu时间到了那么就会让出cpu之后给到T2但是由于此时共享区还在被锁的状态所以T2只好阻塞在锁上等待锁的解锁之后过段时间就会又让出cpu给到T3T3此时也会阻塞在锁上然后过段时间再次让出cpu给T1T1此时拿着锁可以操作共享区所有会继续上次中断的地方继续操作共享区
2、建议锁 假如说当T3拿到cpu时间之后并不阻塞在锁上而是就要强制访问共享区那么也是可以的只不过会造成数据混乱而已所以互斥锁并不是一个强制的概念而是一个建议他的强制性体现在代码逻辑上而不是底层系统的强制操作如果T3的代码逻辑中使用了锁那么T3就无法访问共享区当然T3也可以不使用锁直接访问代码层面也是可以运行的
总结 使用锁来管理线程同步
问题产生 使用两个线程同时向“公共输出”共享区写数据没有加锁机制
效果 打印完全随机各个线程的一帧数据写入都会被其他线程打断、插入其他数据
主要函数 其中trylock函数表示会让当前线程尝试加锁看看能不能加上加不上了先去做自己的事过段时间再来尝试而不是像之前说的“阻塞在锁上”
而五个函数的下面是一个变量这个变量就是互斥量就是锁本身他只有0、1两种取值
大概流程
init、destory 对于init 参数一传入互斥锁的地址 参数二互斥锁的属性如果想使用默认属性那么就传NULL
其中对于restrict关键字 他是用来修饰指针的 可以说这个内存就认定了这个指针注意与指针认定内存有区别(顶层const)
对于顶层const是站在指针的角度对于一个指针来说他只存储某块内存的地址但是该地址还可以被其他指针所存储和操作 而对于restrict是站在内存的角度对于一块内存的操作来说他只认定那个指针其他指针无法操作该内存
返回值成功0。失败返回error number
lock、unlock 代码
1、创建互斥锁全局变量 2、在主线程创建子线程之前要将锁初始化完毕 并在最后所有线程结束后销毁互斥锁 3、在每个线程访问共享区的前后进行加锁和解锁 子线程 主线程
效果 每个线程的数据被完整的加入到了共享区
注意事项锁的粒度
假如说我们把解锁的操作移到循环步的最后 可以看到主线程和子线程都使用加锁和解锁把原来的所有代码包裹起来这样结构上确实很清晰
但是 可以看到最终要么只执行主线程要么只执行子线程
原因 由于线程在解锁之后立马就进入下一个循环使得解锁之后该线程又拿到了锁所以就会一直保持一个线程另一个线程无法拿到锁
所以 我们的加锁和解锁操作只在访问共享区的前后立即执行锁尽量只包含访问共享区的代码部分 最好在解锁之后加个sleep
补充 可以将互斥锁的操作看成整数 初始化时值为1表示当前锁可以被拿取并使用 之后加锁时–那么值变为0表示已经加锁锁目前被占用无法使用其他线程就无法使用锁无法访问共享区了 最后解锁时值变回1表示再次可以使用
try锁 注意他有一个点即加锁失败会直接返回错误号并且不阻塞 lock如果加锁失败是会阻塞在锁上等待锁的释放的
死锁
出现原因 图解 对于第一种情况 反复加锁 当一个线程去拿某个共享区的锁时已经拿到了之后这个线程再次去lock 那么此时由于第一次这个锁已经被lock了。所以第二次的lock会失败然后阻塞在锁上等待锁的释放而能释放锁的线程就是当前阻塞的这个线程所以也就导致线程永远无法继续执行了所以造成死锁
对于第二种情况 如果有两个共享区那么每个共享区都有一个锁如果有一种场景一个线程必须要拿到两个锁才能继续向下执行自己的业务 此时线程1拿到A锁之后他想去拿B锁但是被线程2抢先一步拿到B锁此时线程1lock会失败并且阻塞在B锁而线程2拿到B锁之后去拿A锁由于A锁被线程1拿到了所以线程2也会阻塞在A锁这样两个线程都在阻塞且阻塞在一个“正处于阻塞”的线程所掌握的锁上也就都无法继续向下执行了造成死锁
读写锁
特性 读锁可以共享写锁与上面的互斥锁是一样的
图解
1、当所有的锁都是读锁 遵循读共享的原则那么此时四个锁都可以加锁成功共同去读数据
2、假如说两个线程一个是读、一个是写同时来加锁 假如某一时刻线程1来加读锁线程2加写锁那么会优先让写锁加锁成功注意此时指的是某一刻两个线程同时加锁这种情况很少出现
3、已经有两个读线程加了读锁此时来了两个写线程想要加写锁 如果已经有两个读线程加了读锁此时来了两个写线程想要加写锁那么注意上面说的写锁的优先级高是在r、w锁同时来请求加锁的时刻才会去考虑现在r以及加上了锁那么w锁就必须阻塞等待锁被释放并且是所有的r线程都释放完毕w锁才能加上
但是此时有两把w锁写锁是不会共享的所以只能有一个线程加上w锁这个就要争抢了一旦一个加上了w锁另一个w线程就要继续阻塞等待这就是“写独占”
4、线程1已经加上了r锁此时同时来了两个w锁和一个r锁 线程1已经加上了r锁此时同时来了两个w锁和一个r锁这个时候r锁是不能直接加锁的虽然读锁共享但是要先遵循“写锁优先”。对于同时来的情况只有w锁处理完了。才会去处理r锁所以此时T3会等待T2、T4加锁解锁之后才能去加锁T2、T4也要先等待T1把锁释放了才能去加锁
函数
总览 其中初始化锁、销毁锁、解锁操作都是一个解锁是一个是因为只有一个锁不管指定是读锁还是写锁都是同一把锁
而加锁、和try锁都是两个因为这里涉及到是指定写锁还是读锁
init、destroy rdlock、tryrdlock wrlock、trywrlock unlock 代码 效果 可以看到read线程占比较多这也是读写锁的优势r更多
条件变量
二级目录
二级目录
二级目录
信号量
二级目录
二级目录
二级目录