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

独立网页制作福州seo视频

独立网页制作,福州seo视频,外贸网站设计郑州,网站常用的优化方法有哪些线程的互斥与同步 💫 概念引入⭐️临界资源(Critical Resource):🌟临界区(Critical Section):✨互斥(Mutex): ⚡️结合代码看互斥☄️ 代码逻辑&a…

666

线程的互斥与同步

  • 💫 概念引入
    • ⭐️临界资源(Critical Resource):
    • 🌟临界区(Critical Section):
    • ✨互斥(Mutex):
  • ⚡️结合代码看互斥
    • ☄️ 代码逻辑
    • 💥运行结果
    • 🔥分析
    • 🌪 pthread_mutex_t线程互斥锁
      • 🌈 注意事项

💫 概念引入

在并发编程中,临界资源、临界区和互斥是关键概念,用于处理多个线程或进程对共享资源的访问问题。

⭐️临界资源(Critical Resource):

== 临界资源是指在多线程或多进程环境中,被多个线程或进程共享的资源 ==,例如共享内存、全局变量、文件等。由于多个线程或进程可以同时访问临界资源,如果不加以控制,可能会导致数据的不一致或错误的结果。因此,需要通过临界区和互斥来保护临界资源的访问。

🌟临界区(Critical Section):

== 临界区是指访问临界资源的代码段或区域 ==,在临界区中,对临界资源的访问必须是原子的,即同一时间只能有一个线程或进程在执行临界区的代码。临界区的目的是保证在任意时刻只有一个线程或进程在访问共享的临界资源,从而避免竞争条件(Race Condition)和数据不一致。

✨互斥(Mutex):

互斥是一种用于保护临界资源的同步机制。互斥是一个信号量,它在任意时刻只能被一个线程或进程持有。当一个线程或进程进入临界区时,它会尝试获取互斥锁,如果互斥锁没有被其他线程或进程持有,那么该线程或进程将获得互斥锁,并进入临界区执行代码。其他线程或进程在尝试获取互斥锁时会被阻塞,直到互斥锁被释放。当线程或进程执行完临界区的代码后,会释放互斥锁,允许其他线程或进程获取互斥锁,进入临界区执行代码。

通过使用临界区和互斥,可以确保在任意时刻只有一个线程或进程在访问临界资源,从而避免了竞争条件和数据不一致问题。在多线程或多进程的并发编程中,正确使用临界区和互斥是确保程序正确运行的重要手段。

⚡️结合代码看互斥

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include<iostream>
#include <sys/syscall.h>
using namespace std;int tickets=10000; //票数总量
//抢票逻辑
void *getTicket(void *args)
{//用于将args转换为const char*类型,并将转换结果赋值给name变量。const char *name = static_cast<const char *>(args);while (true){if(tickets>0){usleep(1000);cout << name << " 抢到了票, 票的编号: " << tickets << endl;tickets--;}else{cout << name << "] 已经放弃抢票了,因为没有了..." << endl;break;}}
}int main()
{pthread_t td1;pthread_t td2;pthread_t td3;pthread_t td4;//创建4个线程 执行抢票pthread_create(&td1,nullptr,getTicket,(void*)"td1");pthread_create(&td1,nullptr,getTicket,(void*)"td2");pthread_create(&td1,nullptr,getTicket,(void*)"td3");pthread_create(&td1,nullptr,getTicket,(void*)"td4");pthread_join(td1,nullptr);pthread_join(td2,nullptr);pthread_join(td3,nullptr);pthread_join(td4,nullptr);return 0;
}

☄️ 代码逻辑

这段代码是一个简单的多线程程序,用于模拟多人抢票的场景。代码中使用了pthread库来创建和管理线程。

tickets是一个全局变量,表示票的总数量,初始值为10000。

getTicket函数是抢票的逻辑。每个线程执行此函数,表示一个人在抢票。在函数内部,通过循环不断判断是否还有票,如果有,则输出当前抢到的票的编号,并将票数减1;如果没有了,则输出该线程已经放弃抢票。

pthread_t是一个数据类型,表示线程的ID。

pthread_create函数用于创建线程。它接受四个参数:pthread_t *thread表示接收新创建线程的ID,const pthread_attr_t *attr表示线程的属性,void *(*start_routine) (void *)表示线程的入口函数,void *arg表示传递给入口函数的参数。

pthread_join函数用于等待线程结束。它接受两个参数:pthread_t thread表示要等待的线程ID,void **retval表示线程的返回值。在此代码中,使用nullptr表示不关心线程的返回值。

usleep函数用于让线程睡眠一段时间,模拟抢票过程中的延迟。

在main函数中,创建了4个线程,分别执行getTicket函数来模拟4个人同时抢票的情况。通过pthread_create函数创建线程,并通过pthread_join函数等待线程结束,确保所有线程都执行完毕后程序才结束。

💥运行结果

001

🔥分析

其实代码是存在Bug的
我们试想一下,== tickets-- == 这段代码执行需要几步?
在上一篇博客中有介绍到,线程的运行可能会产生临时数据放在内存,这里的tickets就是如此,我们知道执行–操作是要经过CPU的,那么 执行该代码最少需要3步:

  1. 把tickets拷贝到CPU
  2. CPU执行–操作
  3. 把–后的值放回给对象!
    而在此多线程执行抢票的过程中,随时可能进行线程的切换(由OS调度的),那么就会出现下面的情况:
    线程A在执行–操作 (还没执行完,假设此时A已经–到50张票了,还没把结果放回给对象),此时进行线程切换,B进来执行–操作,但是B并没有拿到最新的余票信息(A没有返回),此时B拿到的就是上一次的余票信息,那么就会出现 == 资源不一致 ==问题 ,该问题是很严重的!!!所以我们要有解决的措施!!!!
  • 解决方案
    保证临界区的原子性 可以通过加锁来实现

🌪 pthread_mutex_t线程互斥锁

pthread_mutex_t是一个线程互斥锁,用于实现线程间的互斥访问共享资源,防止多个线程同时访问造成数据竞争和错误。

互斥锁的作用是在多线程环境下保护临界区(共享资源),只允许一个线程访问临界区,其他线程必须等待互斥锁的释放。一旦一个线程获得了互斥锁,其他线程就无法同时获得该互斥锁,只能等待。

使用pthread_mutex_t需要以下几个步骤:

初始化互斥锁:在使用互斥锁之前,需要对其进行初始化。可以使用pthread_mutex_init函数来完成初始化,也可以使用静态初始化宏PTHREAD_MUTEX_INITIALIZER。

上锁:当一个线程需要访问临界区时,首先要尝试获取互斥锁,即上锁。如果互斥锁已被其他线程占用,则当前线程会阻塞,直到互斥锁被释放。

解锁:当一个线程完成对临界区的访问后,应该释放互斥锁,即解锁。这样其他线程就可以尝试获取互斥锁并访问临界区。

销毁互斥锁:在不再需要使用互斥锁时,应该将其销毁以释放系统资源。可以使用pthread_mutex_destroy函数来销毁互斥锁。

使用互斥锁可以有效地防止多线程访问共享资源时的竞态条件问题,保证程序的正确性和稳定性。但是要注意,滥用互斥锁可能导致线程之间的竞争和性能下降,因此在设计多线程程序时需要慎重考虑互斥锁的使用。

  • 加锁后代码
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include<iostream>
#include <sys/syscall.h>
using namespace std;int tickets=10000; //票数总量pthread_mutex_t mutex; //创建互斥锁
//抢票逻辑
void *getTicket(void *args)
{//用于将args转换为const char*类型,并将转换结果赋值给name变量。const char *name = static_cast<const char *>(args);while (true){pthread_mutex_lock(&mutex);//临界区加锁if(tickets>0){usleep(1000);cout << name << " 抢到了票, 票的编号: " << tickets << endl;tickets--;pthread_mutex_unlock(&mutex); //解锁 }else{cout << name << "] 已经放弃抢票了,因为没有了..." << endl;break;pthread_mutex_unlock(&mutex); //解锁 }}
}int main()
{pthread_mutex_init(&mutex, nullptr); //初始化pthread_t td1;pthread_t td2;pthread_t td3;pthread_t td4;//创建4个线程 执行抢票pthread_create(&td1,nullptr,getTicket,(void*)"td1");pthread_create(&td1,nullptr,getTicket,(void*)"td2");pthread_create(&td1,nullptr,getTicket,(void*)"td3");pthread_create(&td1,nullptr,getTicket,(void*)"td4");pthread_join(td1,nullptr);pthread_join(td2,nullptr);pthread_join(td3,nullptr);pthread_join(td4,nullptr);pthread_mutex_destroy(&mutex);//销毁锁return 0;
}
  • 运行
    0002
    这时候就解决了~

🌈 注意事项

  1. 临界区,只要对临界区加锁,而且加锁的粒度约细越好
  2. 加锁的本质是让线程执行临界区代码串行化
  3. 加锁是一套规范,通过临界区对临界资源进行访问的时候,要加就都要加
  4. 锁保护的是临界区, 任何线程执行临界区代码访问临界资源,都必须先申请锁,前提是都必须先看到锁!
  5. 这把锁,本身不就也是临界资源吗?锁的设计者早就想到了 pthread_mutex_lock: 竞争和申请锁的过程,就是原子的!

Q:为什么在if和else后面都要 执行: pthread_mutex_unlock(&mutex);来释放 直接放在循环的最后会有什么问题?
A:会造成其他在锁外的线程无线在阻塞等待 … 不解锁 不结束!

0000

☀️ 🌤 ⛅️ 🌥 ☁️ 🌦 🌧 ⛈ 🌩 🌨 ❄️ ☃️ ⛄️ 🌬 💨 💧 💦 ☔️ ☂️ 🌊 🌫

http://www.shuangfujiaoyu.com/news/18705.html

相关文章:

  • 怎样做机械租赁的网站建站abc网站
  • 个人建站除了wordpress最简单的网页制作
  • wordpress satellite7郑州seo优化哪家好
  • 网站网页设计中怎么添加页码信息seo指导
  • 音乐网站设计百度关键词排名
  • 网站开发模式b s湖南seo优化公司
  • wordpress带颜色的文字免费外链网站seo发布
  • app下载网站免费网站网址查询工具
  • 做外贸是什么网站商业网站设计
  • 下载好模板该怎么做网站seo关键词怎么选择
  • 扁平化网站设计百度百家自媒体平台注册
  • java做网站建设后台上海推广网站
  • 中国站长广告联盟怎么做
  • 帮别人设计网站网络营销网站设计
  • 网站怎么做认证吗bt磁力搜索引擎在线
  • 西安网站 建设最好的营销策划公司
  • 网站开发建设方案书足球排名最新排名世界
  • 闸北企业网站制作现在搜索引擎哪个比百度好用
  • 本地扬中网站建设个人如何做seo推广
  • 网页设计html代码大全咋结啥seo快排
  • asp做的药店网站模板快手作品推广网站
  • pdf 网站建设短视频营销优势
  • 网站定制的销售情况推广的十种方式
  • 360免费wifi怎么安装长沙网站seo源头厂家
  • discuz做企业网站alexa排名
  • 浏览不良网页的危害广州网站优化方案
  • 广东建设委员会网站账户竞价托管公司
  • 无锡科技网站建设广州百度推广电话
  • 汕头seo外包服务网站seo推广招聘
  • 邢台建网站公司影响seo排名的因素