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

几十元做网站2022推广app赚佣金平台

几十元做网站,2022推广app赚佣金平台,北京建设网上银行,丽江手机网站建设一、临界资源与临界区 多线程会共享例如全局变量等资源&#xff0c;我们把会被多个执行流访问的资源称为临界资源&#xff0c;我们是通过代码访问临界资源的&#xff0c;而我们访问临界资源的那部分代码称为临界区。 实现一个抢票系统 只有一个线程抢票时 #include <ios…

一、临界资源与临界区

多线程会共享例如全局变量等资源,我们把会被多个执行流访问的资源称为临界资源,我们是通过代码访问临界资源的,而我们访问临界资源的那部分代码称为临界区。

实现一个抢票系统

只有一个线程抢票时

#include <iostream>
#include <vector>
#include <unistd.h>#include "Thread.hpp"int num = 10000; std::string GetThreadName()
{static int num = 1;char name[64];snprintf(name, sizeof(name), "thread-%d", num++);return name;
}void Ticket(std::string name)
{while(true){if(num > 0){usleep(1000);printf("%s get ticket: %d\n", name.c_str(), num);num--;}else{break;}}
}int main()
{std::string name1 = GetThreadName();Thread<std::string> t1(name1, Ticket, name1);t1.Start();t1.Join();return 0;
}

正常输出,最终票数为0时退出。

但是当我们启动多个线程同时抢票时,num就是临界资源,使用num的那部分代码就是临界区

#include <iostream>
#include <vector>
#include <unistd.h>#include "Thread.hpp"int num = 10000; std::string GetThreadName()
{static int num = 1;char name[64];snprintf(name, sizeof(name), "thread-%d", num++);return name;
}void Ticket(std::string name)
{while(true){if(num > 0){usleep(1000);printf("%s get ticket: %d\n", name.c_str(), num);num--;}else{break;}}
}int main()
{std::string name1 = GetThreadName();Thread<std::string> t1(name1, Ticket, name1);std::string name2 = GetThreadName();Thread<std::string> t2(name2, Ticket, name2);std::string name3 = GetThreadName();Thread<std::string> t3(name3, Ticket, name3);std::string name4 = GetThreadName();Thread<std::string> t4(name4, Ticket, name4);t1.Start();t2.Start();t3.Start();t4.Start();t1.Join();t2.Join();t3.Join();t4.Join();return 0;
}

可以看到出现了0和负数的票数,这是因为当票数只剩1时,有多个执行流在同一时间通过了if判断,使得能继续进行减票操作。

vs下自减操作的反汇编,分为三步:先从内存拿数据,再把数据减1,最后把数据拷贝到内存

多个执行流同时访问临界资源例如自减操作,由于--操作不是原子性的(我们认为一条汇编指令是原子性的,是不会被中断的。但--操作转为汇编指令后,需要多条指令才能完成),当--操作执行到一半切换到其他线程会导致数据不一致的问题。这种情况下需要通过锁把临界区保护起来,每次只让一个执行流访问临界资源,避免数据不一致问题。

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

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

二、使用锁的方法

1.创建锁

如果定义一个全局的锁,直接使用pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER用宏初始化。

如果定义一个局部锁,要使用pthread_mutex_init方法创建,参数attr设为nullptr

2.加锁解锁

使用pthread_mutex_lock加锁,传递锁的地址,

解锁用pthread_mutex_unlock

当我们使用锁后,就能保证每次只有一个执行流能访问临界资源。

#include <iostream>
#include <vector>
#include <unistd.h>#include "Thread.hpp"int num = 10000;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //定义一个全局锁std::string GetThreadName()
{static int num = 1;char name[64];snprintf(name, sizeof(name), "thread-%d", num++);return name;
}void Ticket(std::string name)
{while(true){pthread_mutex_lock(&mutex); //加锁if(num > 0){usleep(1000);printf("%s get ticket: %d\n", name.c_str(), num);num--;pthread_mutex_unlock(&mutex); //解锁}else{pthread_mutex_unlock(&mutex); //解锁break;}}
}int main()
{std::string name1 = GetThreadName();Thread<std::string> t1(name1, Ticket, name1);std::string name2 = GetThreadName();Thread<std::string> t2(name2, Ticket, name2);std::string name3 = GetThreadName();Thread<std::string> t3(name3, Ticket, name3);std::string name4 = GetThreadName();Thread<std::string> t4(name4, Ticket, name4);t1.Start();t2.Start();t3.Start();t4.Start();t1.Join();t2.Join();t3.Join();t4.Join();return 0;
}

结果正常,但是速度慢了很多,因为要不断申请锁和释放锁

加锁解锁的过程是安全的

三、可重入和线程安全

1.概念

线程安全:多个线程并发同一段代码时,不会出现不同的结果。常见对全局变量或者静态变量进行操作, 并且没有锁保护的情况下,会出现该问题。

重入:同一个函数被不同的执行流调用,当前一个流程还没有执行完,就有其他的执行流再次进入,我们称之为重入。一个函数在重入的情况下,运行结果不会出现任何不同或者任何问题,则该函数被称为可重入函数,否则,是不可重入函数。

2.常见的线程不安全的情况

1.不保护共享变量的函数

2.函数状态随着被调用,状态发生变化的函数

3.返回指向静态变量指针的函数

4.调用线程不安全函数的函数

3.常见的线程安全的情况

1.调用了malloc/free函数,因为malloc函数是用全局链表来管理堆的

2.调用了标准I/O库函数,标准I/O库的很多实现都以不可重入的方式使用全局数据结构

3.可重入函数体内使用了静态的数据结构

4.常见可重入的情况

1.不使用全局变量或静态变量

2.不使用用malloc或者new开辟出的空间

3.不调用不可重入函数不返回静态或全局数据,所有数据都有函数的调用者提供

4.使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据

5.可重入与线程安全联系

1.函数是可重入的,那就是线程安全的

2.函数是不可重入的,那就不能由多个线程使用,有可能引发线程安全问题

3.如果一个函数中有全局变量,那么这个函数既不是线程安全也不是可重入的。

6.可重入与线程安全区别

1.可重入函数是线程安全函数的一种

2.线程安全不一定是可重入的,而可重入函数则一定是线程安全的。

3.如果将对临界资源的访问加上锁,则这个函数是线程安全的,但如果这个重入函数若锁还未释放则会产生 死锁,因此是不可重入的。

四、死锁

死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。

1.死锁四个必要条件

1.互斥条件:一个资源每次只能被一个执行流使用

2.请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不放

3.不剥夺条件: 一个执行流已获得的资源,在末使用完之前,不能强行剥夺

4.循环等待条件: 若干执行流之间形成一种头尾相接的循环等待资源的关系

2.避免死锁

1.破坏死锁的四个必要条件

2.加锁顺序一致

3.避免锁未释放的场景

4.资源一次性分配

3.避免死锁算法

1.死锁检测算法

2.银行家算法

一个锁会造成死锁吗?

答案是会的,当一个线程申请完一个锁,访问完临界资源后,接下来该释放锁了,但是代码却写成了加锁,这就会导致死锁问题。

http://www.ritt.cn/news/15894.html

相关文章:

  • 营销型网站建设口碑好最有效的15个营销方法
  • asp 网站名字软件开发公司联系方式
  • 长沙网建站交换友情链接的渠道
  • 上海网站建设案例seoheuni
  • 做商城网站多少钱百度关键词查询工具
  • 广东营销型网站建设广东网站优化公司
  • 设计师网站导航青年帮百度百科官网首页
  • 免费网站湖南疫情最新消息今天
  • 网站备案要关闭吗站长工具查询seo
  • 阳江网站制作网络销售是干嘛的
  • 深圳网站维护页面设计模板网站建站哪家好
  • 做网站可以用新建项目的方式吗账户竞价托管费用
  • 西安SEO网站建设小红书关键词排名怎么做
  • 商城网站建设专业公司刷推广链接
  • asp网站怎么做404页面福州网站建设团队
  • 网站建设jw100高粱seo博客
  • 手机平台网站开发外链工厂 外链
  • 北京手机网站建设公司哪家好外贸营销系统
  • 晚上做设计挣钱的网站网络营销计划包括哪七个步骤
  • 巢湖网 网站网站建设推广多少钱
  • 免费网站seo软件网络推广app是干什么的
  • 北京企业建设网站制作广州网站优化费用
  • 网站交易模块怎么做成品短视频app源码的优点
  • 漳州最专业的网站建设公司做一个公司网页多少钱
  • 上海做兼职上哪个网站厦门seo
  • 北京做网站开发公司有哪些东莞网站建设工作
  • 网站设置5个关键词外贸找客户有什么网站
  • 网页制作的常用工具seo信息查询
  • 做网站 后端是谁来做的网站推广途径和推广要点有哪些?
  • 做食品那些网站专业做网站设计