Linux下线程的同步与互斥

打印 上一主题 下一主题

主题 901|帖子 901|积分 2703

开头我们来写一个简单的步伐,实现用多线程的方式来抢票,代码如下:


运行完结果后发现,我这只有一万张票,在if条件判断里我也做了判断,怎么会干到-2来了呢?
运用线程的理论知识我们知道,ticketnum在线程中属于共享资源,它不具有原子性,在我们必要对变量进行减减的时间,内存会将变量存入cpu中减减,然后再把减完后的内容写入内存里三步,
但减减完的数据还没写入内存的时间,进程就被切换了,也就是上面三步线程没做完,所以不具备原子性,当然我们做if判断的时间,也是一种计算也是要进cpu的,在末了数据都只是1的时间,四个线程都进去了,随着变量被减减,他就会被减到负数。为了避免这种情况,可以使用互斥锁;
一,mutex


锁的使用最好是在临界区内,锁最好涵盖代码少一点,要不然会影响运行效率,假如使用全局锁,可用PTHREAD_MUTEX_TNITIALIZER来初始化锁,这样只必要声明:

初始化好了怎么加锁?:

可以看到,加锁解锁都得在临界区内加,并且不能大块代码的加锁。

可以看到,对临界区加锁之后,变量减减就变成具有原子性的了,加锁的本质就是对资源进行预定,整体使用资源,假如申请锁的时间,锁被别人拿走了,这时间其他线程就会阻塞等待直到前面线程运行完再竞争,线程在访问临界区代码的时间,可以不可以切换??可以切换!!
我被切走的时间,别人能进来吗??不能!我是抱着锁,被切换的!!不就是串行吗!效率低的原因!原子性!上面是全局初始化锁的方式,不用我们用init和destory方法,下面就是用局部初始化锁的方式书写代码:

起首对锁进行初始化,再在结束位置销毁锁,

其结果也是一样的:

二,cond(同步)

根据mutex的学习,来映伸出下一个问题,当一个线程拿完锁回到队列中再次与其他线程竞争锁的时间,会有部分概率重复使用锁(饥饿问题),其他线程会长时间得不到资源,会导致步伐运行效率不高,这时间可以使用同步的方法来办理,就好比排队一样,排完队领完东西还要再领就得重新在队伍后面排队,这就叫同步
同步的意义:
互斥可以包管安全性,但是安全不肯定合理高效
同步是包管安全的情况下,让代码变得合理和高效。
起首我们先来了解对应接口:起首来介绍同步的初始化,看图:

可以发现,他和mutex的初始化是一样的,可以全局初始化也可以局部初始化,在全局使用初始化可以不用调用init和destory函数。
下一个接口,让指定的线程在指定的环境变量等待,假如别人不唤醒就一直等。

signal接口,可以唤醒在特定条件变量下的一个线程:
broadcast可以唤醒特定条件变量下指定的所有线程。

条件变量是一个用来进行线程同步的特性,内部要维护线程队列。
下面利用之前的抢票代码来做线程同步的接口训练:

可以看到,我先把票数设为零,线程都会去wait这里等待:


可以看到线程都在阻塞等待,这时间我们可以通过放票然后唤醒线程的方式来抢票:


可以看到线程被唤醒但是没执行,是因为在wait那里会重新申请和释放锁,就相当于已经有锁了但是又去申请锁,代码就会被挂起,这个后面细讲,在while那里再次解锁来让我们看到测试结果先:








免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

美食家大橙子

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表