当前位置: 首页 > news >正文

磁力搜索网站怎么做的网站和app设计区别

磁力搜索网站怎么做的,网站和app设计区别,宝塔搭建wordpress的基本设置,网站开发背景400字目录 概念补充 互斥量mutex 为什么有互斥 例:多线程抢票 --操作 互斥量(锁) 操作 例:多线程抢票 补充 互斥量的封装 小知识 概念补充 临界资源:多线程执行流共享的资源就叫做临界资源 临界区:每个线程内部,访问临界资源的代码,叫做临界区 互斥:任何时刻,互斥保证只有…

目录

概念补充

互斥量mutex

为什么有互斥

例:多线程抢票

--操作

互斥量(锁)

操作

例:多线程抢票

补充

互斥量的封装

小知识


概念补充

临界资源:多线程执行流共享的资源就叫做临界资源

临界区:每个线程内部,访问临界资源的代码,叫做临界区


互斥:任何时刻,互斥保证只有一个执行流进入临界区,访问临界资源,对临界资源起保护作用

原子性:不会被任何调度机制打断的操作,该操作只有两种状态,完成和未完成        

互斥量mutex

为什么有互斥

多线程如果并发(同一时间段切换着访问同一资源)访问了共享的资源,共享资源的安全性无法保证.

比如

1.多个线程同时访问显示器文件,向屏幕中打印数据,会因为线程调度切换导致打印错乱的问题;

2.如果有全局变量,多个线程都访问会出问题

例:多线程抢票
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>int ticket = 100;void *route(void *arg)
{char *id = (char*)arg;while ( 1 ) {if ( ticket > 0 ) {usleep(1000);printf("%s sells ticket:%d\n", id, ticket);ticket--;} else {break;}}
}
int main(  )
{pthread_t t1, t2, t3, t4;pthread_create(&t1, NULL, route, "thread 1");pthread_create(&t2, NULL, route, "thread 2");pthread_create(&t3, NULL, route, "thread 3");pthread_create(&t4, NULL, route, "thread 4");pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);pthread_join(t4, NULL);
}

执行到最后,票数会变为负数,为什么呢?

因为在汇编层面,代码会变成多条汇编语句,而单条汇编语句的执行是不会被打断的,执行了就一定会执行完,是原子的; 

当执行到ticket为1时,某线程可能刚执行完ticket>0的汇编语句,线程就因为时间片耗尽等原因被切换了,其他线程这时执行ticket>0的汇编语句取到的也是1,然后再次切换,所有线程都在ticket>0这里判断成功了,之后向下执行,导致ticket最后减到了-3.

这就是多线程访问公共资源导致的问题之一.

--操作

--被汇编为多条指令,可能一个线程刚从内存取数据,时间片到了,调度另一个线程,另一个线程取数据,分析数据,执行--,然后结束,调度回之前的线程,结果两个线程执行完,结果只--了一次.

所以--和++操作多线程下也是不安全的.

互斥量(锁)

要解决上面的问题,需要做到三点

1.代码要有互斥行为:当代码进入临界区时,不允许其他线程进入临界区

2.如果多个线程同时要求执行临界区的代码,并且临界区没有线程在执行,那么只能允许⼀个线程进入该临界区。

3.如果线程不在临界区中执行,那么该线程不能阻止其他线程进入临界区


linux提供了一把锁,叫互斥量

操作

全局互斥量

直接使用宏来初始化一个全局mutex锁

局部互斥量

局部互斥量需要初始化和销毁

申请锁和释放锁

int pthread_mutex_lock(pthread_mutex_t *mutex);//申请

int pthread_mutex_unlock(pthread_mutex_t *mutex);//释放

使用时,将临界区代码放在申请和释放锁的内部.

例:多线程抢票

#include <iostream>

#include <unistd.h>

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

int tickets = 100;

void *func(void *args)

{

    (void*)args;

    while(true)

    {

        {

            pthread_mutex_lock(&lock);

            if(tickets>0)

            {

                sleep(0.1);

                printf("剩余票数: %d\n",--tickets);

            }

            else

            {

                break;

            }

            pthread_mutex_unlock(&lock);

        }//加一层花括号表示锁住的区域

       

    }

    return (void*)0;

}


 

int main()

{

    pthread_t t1,t2,t3;

    pthread_create(&t1,nullptr,func,nullptr);

    pthread_create(&t2,nullptr,func,nullptr);

    pthread_create(&t3,nullptr,func,nullptr);

    pthread_join(t1,nullptr);

    pthread_join(t2,nullptr);

    pthread_join(t3,nullptr);

    return 0;

}

补充

1.互斥量会被多个线程并发访问,所以它也是临界资源,怎么保证自身的安全?

解: 锁是原子的

实现原子性的方案:

(1)硬件上:关闭所有中断

(2)软件上:因为每一条汇编语句都是原子的,所以只通过一条汇编语句实现互斥量(锁)即可

linux中使用交换的机制,大体流程:

在内存中会有mutex变量的数据区域,存放1,cpu中有寄存器存放0

程序执行到锁这里时,直接交换内存和cpu寄存器中的值,然后判断寄存器中的值,是1,继续执行,是0,该线程不向下执行,而是或者阻塞等待,或者不断重复申请,这样只有申请到1的线程可以执行临界区代码,其他线程只能等.

解锁就是将1设置到内存中的mutex区域,以便其他线程申请

2.申请成功,线程继续运行,申请失败,线程会被阻塞

3.如果进入了临界区,线程还会被切换导致并发问题吗?

会被切换,但即使被切换,此进程未解锁时,其他线程进行申请锁也会失败,阻塞住

互斥量的封装

<Lock.hpp>

#pragma once

#include <iostream>

#include <unistd.h>

#include <pthread.h>

class Mutex

{

    pthread_mutex_t _mutex;

public:

    Mutex(const Mutex&) = delete;

    const Mutex& operator = (const Mutex&) = delete;

    Mutex()

    {

        int n = pthread_mutex_init(&_mutex,nullptr);

        (void)n;

    }

    void Lock()

    {

        int n = pthread_mutex_lock(&_mutex);

        (void)n;

    }

    void Unlock()

    {

        int n = pthread_mutex_unlock(&_mutex);

        (void)n;

    }

    pthread_mutex_t *Get()

    {

        return &_mutex;

    }

    ~Mutex()

    {

        int n = pthread_mutex_destroy(&_mutex);

        (void)n;

    }

};

class LockGuard

{

    Mutex &_mutex;

public:    

    LockGuard(Mutex& mutex):_mutex(mutex)

    {

        _mutex.Lock();

    }

    ~LockGuard()

    {

        _mutex.Unlock();

    }

};

LockGarud用来管理锁

所以多线程抢票的代码可以改为

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include "Lock.hpp"int ticket = 1000;Mutex mutex;
void *route(void *arg)
{char *id = (char *)arg;while (1){LockGuard lockguard(mutex); // 使⽤RAII⻛格的锁 if (ticket > 0){usleep(1000);printf("%s sells ticket:%d\n", id, ticket);ticket--;}else{break;}}return nullptr;
}
int main(void)
{pthread_t t1, t2, t3, t4;pthread_create(&t1, NULL, route, (void*)"thread 1");pthread_create(&t2, NULL, route, (void*)"thread 2");pthread_create(&t3, NULL, route, (void*)"thread 3");pthread_create(&t4, NULL, route, (void*)"thread 4");pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);pthread_join(t4, NULL);
}

小知识

1.锁的使用的最佳实践: 加锁和解锁时,囊括的区域尽量是最小集

2.互斥的负面影响:降低程序的运行效率

http://www.dtcms.com/a/469663.html

相关文章:

  • 西安网站建设公司都有哪些网站设计开发文档模板下载
  • C++设计模式_结构型模式_桥接模式Bridge
  • 关于flutter插件的存储位置问题
  • 把“Mixed Content”吃干抹净——一次 https→http 踩坑实录
  • 中山大学联合项目 论文解读 | iManip:面向机器人操作的技能增量学习
  • Unity:Json笔记——Json文件格式、JsonUtlity序列化和反序列化
  • 第八章 惊喜15 小萍收获初会
  • RabbitMQ基础知识与Spring Boot 3.x集成案例
  • 租房网站建设多少钱网站域名怎么改
  • Redis CPU高负载案例分析
  • ARMv9 CCA机密计算架构演进技术解析:重塑云原生时代的数据安全基石
  • 湖州网站设计浙北数据最新发布的手机有哪些
  • AD加域账号权限设置
  • 解决idea报错:Error running TrustApexCrmApplication. Command line is too long
  • 网站开发淄博进口商品代理平台
  • systme V共享内存(version1)
  • 万网网站制作wordpress投稿管理系统
  • python(47) : 快速截图[Windows工具(2)]
  • VSCODE GDB调试
  • 江西企业网站定制wordpress网页效果
  • CCF-GESP 等级考试 2024年6月认证C++三级真题解析
  • 前端学习1(学习时间:30分钟简单)
  • vlan范围
  • 北京顺义做网站编程正规学校有哪几所
  • 跨平台向量库:Linux Windows 上一条龙部署 PostgreSQL 向量扩展
  • 基于YOLO与DeepSort的高效行人跟踪算法研究
  • [GazeTracking] 视线追踪核心逻辑 | Dlib库
  • docker安装Xinference
  • 从标准化到个性化:基于代理模式的智能办公工具技术实现与趋势
  • AI(学习笔记第十一课) 使用langchain的multimodality