【linux系统编程】线程互斥

在这里插入图片描述

点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃

1.线程互斥

到目前为止我们学了线程概念,线程控制接下来我们进行下一个话题,线程互斥。

有没有考虑过这样的一个问题,既然线程一旦被创建,几乎所有资源都是被所有线程共享的。 那多个线程访问同一份共享资源有没有什么问题?

下面我们模拟一下抢票的场景,看到底有没有什么问题

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string>

//共享资源,火车票
int ticket = 10000;

void *GetTicket(void *args)
{
   
   
    string name = static_cast<const char *>(args);
    while (true)
    {
   
   
        if (ticket > 0)
        {
   
   
            cout << name << " 正在进行抢票: " << ticket << endl;
            ticket--;
            //以微秒为单位进行休眠,模拟真实的抢票要花费的时间
            usleep(1000);
        }
        else
        {
   
   
            break;
        }
    }
}

int main()
{
   
   
    pthread_t t1,t2,t3,t4;
    pthread_create(&t1,nullptr,GetTicket,(void*)"thread->1");
    pthread_create(&t2,nullptr,GetTicket,(void*)"thread->2");
    pthread_create(&t3,nullptr,GetTicket,(void*)"thread->3");
    pthread_create(&t4,nullptr,GetTicket,(void*)"thread->4");

    pthread_join(t1,nullptr);
    pthread_join(t2,nullptr);
    pthread_join(t3,nullptr);
    pthread_join(t4,nullptr);
    return 0;
}

在这里插入图片描述
这好像没出问题啊,到0就停止了。

我们想看到的现象是抢到负数票,那怎么实现呢?
既然想看到抢到负数票,就需要尽可能的让多个线程交叉执行。
多个线程交叉执行的本质:就是让调度器尽可能的频繁发生线程调度与切换。
线程一般在时候发生切换呢?
时间片到了,来了更高优先级的线程,线程等待的时候。
那线程是什么时候检测上面的问题呢?
从内核态返回用户态的时候,线程要对调度状态进行检测,如果可以,就直接发生线程切换。

那修改一下代码

void *GetTicket(void *args)
{
   
   
    string name = static_cast<const char *>(args);
    while (true)
    {
   
   
        if (ticket > 0)
        {
   
   
        	//线程进来之后先休眠,要被切走
        	usleep(1000);
            cout << name << " 正在进行抢票: " << ticket << endl;
            ticket--;
            //以微秒为单位进行休眠,模拟真实的抢票要花费的时间
            //usleep(1000);
        }
        else
        {
   
   
            break;
        }
    }
}

在这里插入图片描述
出问题了,放了10000张票,结果抢到了10002张票。现象就是这个样子。那为什么会出现这样的问题?

在这里插入图片描述
所谓判断的本质逻辑:
1.读取内存数据到CPU内部寄存器中
2.进行判断

所以ticket=1,多个线程可以同时执行这个判断语句。对不对?
答案是不对的。
我们只有一个CPU,只有一份寄存器,不能同时判断,但是注意我们写了usleep语句,线程是要被切换走的,但是寄存器中的内容是属于这个线程的,因此1也要被切走
在这里插入图片描述
剩下的线程就可以开始竞争执行if语句判断,但很不幸最终都是进去后先休眠。
在这里插入图片描述
当线程1被唤醒恢复上下文,执行到ticket- -;
ticket- -有三个步骤:1.读取数据,2.更改数据,3.写回数据
此时线程1从内存中读取ticke还是1,最后写回内存ticket为0
在这里插入图片描述
线程2此时醒来恢复上下文,它不知道内存中ticket此时是0,往下执行到ticket- -,此时取到ticket是0,最后写回内存中ticket是-1
在这里插入图片描述
线程3也醒来,和上面一样,执行到ticket- -,从内存取到数据为-1,写回内存中是-2
在这里插入图片描述
就是因为我们判断和更新分开,而在中间发生了大量的线程切换,最终可能出现ticket本来就是1了,但是你却放了大量线程同时进来对ticket变量做减减操作,进而导致我们的数据出现了负

评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值