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

汕头模板做网站手机网站用什么软件做的好处

汕头模板做网站,手机网站用什么软件做的好处,密云网站制作案例,四川城乡建设厅建筑特种作业证书目录 线程互斥 进程线程间的互斥相关背景概念 互斥量mutex 互斥量的接⼝ 初始化互斥量 初始化互斥量有两种⽅法 销毁互斥量 互斥量加锁和解锁 加锁的使用 互斥量实现原理探究 互斥量的封装 Mutex.hpp Main.cc 线程互斥 进程线程间的互斥相关背景概念 临界资源&…

目录

线程互斥

进程线程间的互斥相关背景概念

互斥量mutex

互斥量的接⼝

初始化互斥量

初始化互斥量有两种⽅法

销毁互斥量

互斥量加锁和解锁

加锁的使用

互斥量实现原理探究

互斥量的封装

Mutex.hpp

Main.cc


线程互斥

进程线程间的互斥相关背景概念

  • 临界资源:多线程执行流共享的资源就叫做临界资源
  • 临界区:每个线程内部,访问临界资源的代码,就叫做临界区
  • 互斥:任何时刻,互斥保证有且只有⼀个执⾏流进⼊临界区,访问临界资源,通常对临界资源起 保护作⽤
  • 原⼦性(后⾯讨论如何实现):不会被任何调度机制打断的操作,该操作只有两态,要么完成, 要么未完成

互斥量mutex

  • ⼤部分情况,线程使⽤的数据都是局部变量,变量的地址空间在线程栈空间内,这种情况,变量 归属单个线程,其他线程⽆法获得这种变量。
  • 但有时候,很多变量都需要在线程间共享,这样的变量称为共享变量,可以通过数据的共享,完 成线程之间的交互。
  • 多个线程并发的操作共享变量,会带来⼀些问题。
// 操作共享变量会有问题的售票系统代码 
#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( void )
{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);
}
⼀次执⾏结果:thread 4 sells ticket:100...thread 4 sells ticket:1thread 2 sells ticket:0thread 1 sells ticket:-1thread 3 sells ticket:-

要解决以上问题,需要做到三点:

  • 代码必须要有互斥⾏为:当代码进⼊临界区执⾏时,不允许其他线程进⼊该临界区。
  • 如果多个线程同时要求执⾏临界区的代码,并且临界区没有线程在执⾏,那么只能允许⼀个线程 进⼊该临界区。
  • 如果线程不在临界区中执⾏,那么该线程不能阻⽌其他线程进⼊临界区。

要做到这三点,本质上就是需要⼀把锁。Linux上提供的这把锁叫互斥量

互斥量的接⼝

初始化互斥量

初始化互斥量有两种⽅法

⽅法1,静态分配:  PTHREAD_MUTEX_INITIALIZER是一个宏,用于静态初始化互斥锁。它只能用于静态存储期的对象(如全局变量或静态变量),不能用于动态分配的互斥锁。全局使用不需要销毁

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER

⽅法2,动态分配:  pthread_mutex_init是一个函数,用于动态初始化互斥锁。它可以用于任何类型的互斥锁,包括动态分配的互斥锁 ,局部使用需要销毁

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const 
pthread_mutexattr_t *restrict attr);参数:mutex:要初始化的互斥量attr:NULL

销毁互斥量

销毁互斥量需要注意:

  • 使⽤ PTHREAD_ MUTEX_ INITIALIZER 初始化的互斥量不需要销毁 

  • 不要销毁⼀个已经加锁的互斥量

  • 已经销毁的互斥量,要确保后面不会有线程再尝试加锁

int pthread_mutex_destroy(pthread_mutex_t *mutex);

互斥量加锁和解锁

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);返回值:成功返回0,失败返回错误号

调⽤ pthread_ lock 时,可能会遇到以下情况:

  • 互斥量处于未锁状态,该函数会将互斥量锁定,同时返回成功
  • 发起函数调⽤时,其他线程已经锁定互斥量,或者存在其他线程同时申请互斥量,但没有竞争到 互斥量,那么pthread_lock调⽤会陷⼊阻塞(执⾏流被挂起),等待互斥量解锁

加锁的使用

注释掉的是使用互斥量的接⼝的方法  ,保留的是C++11的加锁

1. 锁本身是全局的,那么锁也是共享资源!谁保证锁的安全??

pthread_mutex:加锁和解锁被设计成为原子的了 --- TODO??

2. 如何看待锁呢?二元信号量就是锁!

   2.1 加锁本质就是对资源展开预订!

   2.2 整体使用资源!!

3. 如果申请锁的时候,锁被别人已经拿走了,怎么办?其他线程要进行阻塞等待

4. 线程在访问临界区代码的时候,可以不可以切换??可以切换!!

   4.1 我被切走的时候,别人能进来吗??不能!我是抱着锁,被切换的!!不就是串行吗!效率低的原因!原子性!

5. 不遵守这个约定??bug!

使用C++11的锁

#include <iostream>
#include <vector>
#include "Thread.hpp"
#include <mutex>   //c++11的锁using namespace ThreadModule;#define NUM 4// 1. 锁本身是全局的,那么锁也是共享资源!谁保证锁的安全??
// pthread_mutex:加锁和解锁被设计成为原子的了 --- TODO??
// 2. 如何看待锁呢?二元信号量就是锁!
//    2.1 加锁本质就是对资源展开预订!
//    2.2 整体使用资源!!
// 3. 如果申请锁的时候,锁被别人已经拿走了,怎么办?其他线程要进行阻塞等待
// 4. 线程在访问临界区代码的时候,可以不可以切换??可以切换!!
//    4.1 我被切走的时候,别人能进来吗??不能!我是抱着锁,被切换的!!不就是串行吗!效率低的原因!原子性!
// 5. 不遵守这个约定??bug!// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int ticketnum = 10000; // 共享资源,临界资源
std::mutex gmtx;   //定义c++11的锁 ,定义一个全局互斥量class ThreadData
{
public:std::string name;//pthread_mutex_t *lock_ptr;
};void Ticket(ThreadData &td)
{while (true){gmtx.lock();//加锁//pthread_mutex_lock(td.lock_ptr); // 加锁if (ticketnum > 0){usleep(1000);// 1. 抢票printf("get a new ticket, who get it: %s, id: %d\n", td.name.c_str(), ticketnum--);gmtx.unlock();  //解锁//pthread_mutex_unlock(td.lock_ptr); // ??// 2. 入库模拟usleep(50);}else{//pthread_mutex_unlock(td.lock_ptr); // ??gmtx.unlock();  //解锁break;}}
}int main()
{// pthread_mutex_t lock;// pthread_mutex_init(&lock, nullptr);// 1. 构建线程对象std::vector<Thread<ThreadData>> threads;for (int i = 0; i < NUM; i++){ThreadData *td = new ThreadData();//td->lock_ptr = &lock;// td->lock_ptr =nullptr;threads.emplace_back(Ticket, *td);td->name = threads.back().Name();}// 2. 启动线程for (auto &thread : threads){thread.Start();}// 3. 等待线程for (auto &thread : threads){thread.Join();}// pthread_mutex_destroy(&lock);return 0;
}

使用全局的锁

#include <iostream>
#include <vector>
#include "Thread.hpp"
#include <mutex>   //c++11的锁using namespace ThreadModule;#define NUM 4pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int ticketnum = 10000; // 共享资源,临界资源
// std::mutex gmtx;   //定义c++11的锁class ThreadData
{
public:std::string name;pthread_mutex_t *lock_ptr;
};void Ticket(ThreadData &td)
{while (true){// gmtx.lock();//加锁pthread_mutex_lock(td.lock_ptr); // 加锁if (ticketnum > 0){usleep(1000);// 1. 抢票printf("get a new ticket, who get it: %s, id: %d\n", td.name.c_str(), ticketnum--);// gmtx.unlock();  //解锁pthread_mutex_unlock(td.lock_ptr); // ??// 2. 入库模拟usleep(50);}else{pthread_mutex_unlock(td.lock_ptr); // ??// gmtx.unlock();  //解锁break;}}
}int main()
{// pthread_mutex_t lock;// pthread_mutex_init(&lock, nullptr);// 1. 构建线程对象std::vector<Thread<ThreadData>> threads;for (int i = 0; i < NUM; i++){ThreadData *td = new ThreadData();td->lock_ptr = &lock;threads.emplace_back(Ticket, *td);td->name = threads.back().Name();}// 2. 启动线程for (auto &thread : threads){thread.Start();}// 3. 等待线程for (auto &thread : threads){thread.Join();}// pthread_mutex_destroy(&lock);return 0;
}

互斥量实现原理探究

        经过上⾯的例⼦,⼤家已经意识到单纯的 i++ 或者 ++i 都不是原⼦的,有可能会有数据⼀致性 问题

为了实现互斥锁操作,⼤多数体系结构都提供了swap或exchange指令,该指令的作⽤是把寄存器和 内存单元的数据相交换,由于只有⼀条指令,保证了原⼦性,即使是多处理器平台,访问内存的总线周 期也有先后,⼀个处理器上的交换指令执⾏时另⼀个处理器的交换指令只能等待总线周期。现在 我们把lock和unlock的伪代码改⼀下

互斥量的封装

Mutex.hpp

#pragma once
#include<iostream>
#include<pthread.h>
#include <unistd.h>namespace LockModule
{class Mutex{public://防止锁被拷贝 Mutex(const Mutex&) = delete;const Mutex& operator = (const Mutex&) = delete;Mutex(){int n = ::pthread_mutex_init(&_lock ,nullptr);if(n!= 0) std::cout<<"pthread_mutex_init error"<<std::endl;}void Lock(){int n = ::pthread_mutex_lock(&_lock);if(n!= 0) std::cout<<"lock error"<<std::endl;}void Unlock(){int n =::pthread_mutex_unlock(&_lock);if(n!= 0) std::cout<<"unlock error"<<std::endl;}~Mutex(){int n = pthread_mutex_destroy(&_lock);if(n!= 0) std::cout<<"destroy error"<<std::endl;}private:pthread_mutex_t _lock;};class LockGuard{public:LockGuard(Mutex &mtx):_mtx(mtx){_mtx.Lock();}~LockGuard(){_mtx.Unlock();}private:Mutex &_mtx;};}

使用

Main.cc

#include "Mutex.hpp"using namespace LockModule;
int ticket=1000;Mutex mtx;void *route(void *arg)
{char *id = (char *)arg;while (1){//RAII 风格的加锁LockGuard  lockguard(mtx);//在代码块中定义的临时对象 ,处了这个块 就自己析构了 ,这个块就是临界区if (ticket > 0){usleep(1000);printf("%s sells ticket:%d\n", id, ticket);ticket--;}else{break;}}return nullptr;
}// void *route(void *arg)
// {
//     char *id = (char *)arg;
//     while (1)
//     {
//        mtx.Lock();
//         if (ticket > 0)
//         {
//             usleep(1000);
//             printf("%s sells ticket:%d\n", id, ticket);
//             ticket--;
//             mtx.Unlock();
//         }
//         else
//         {
//             mtx.Unlock();
//             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);
}

http://www.dtcms.com/wzjs/799992.html

相关文章:

  • 网站备案账号密码怎么注册公司教程
  • 上海市政网官网南京企业网站做优化
  • led灯什么网站做推广好济南网站设计价格
  • 网站百度搜索第一页化妆品网站建设的设计思路
  • 平面设计师素材网站内蒙古网站建设 阿里巴巴
  • 泰安手机网站建设公司企业贷款政策最新消息2022
  • 建设通是个什么网站品牌营销公司
  • 成都网站建设网站建设哪家好微信小程序开店怎么弄
  • 郑州营销网站公司地址wordpress页面发布失败为什么
  • 万网域名指向网站想学做宝宝食谱上什么网站
  • 一般网站建设公司有多少客户啊做抽奖的网站犯法吗
  • 网站界面用什么软件做wordpress 不显示首页
  • 网站主播有些网站突然无法访问
  • 订餐网站建设网站图标用代码代替
  • 免费下载网站模板wordpress上传更新
  • 看电视剧的免费网站app下载制作app免费网站模板
  • 网站建设怎么赚钱郑州seo规则
  • 企业做网站电话约见客户的对话什么是网站优化主要包括那几个
  • 建筑业务网站建设wordpress主题知言
  • 动态ip服务器可以做网站吗1元购类似网站架设药多少钱
  • 做网站需求需要沟通什么去哪个网站可以接单做ps等等
  • 企业在网站推广免费行情软件app网站大全
  • 网站做反向代理对百度收录有影响吗厦门市建设局官网
  • 红酒营销型网站建设wordpress阿里云图片不显示不出来
  • 苏州知名高端网站建设网络公司个人如何开发手机app
  • 自己电脑做网站要下载免费域名注册网站源码
  • 简洁网站布局专业ppt制作价格
  • 通过社交网站来做招聘决定简单的个人网站html
  • 做网站练手做童车外贸上哪个网站
  • 网站内备案名称 修改网站开发报价范围