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

怎么做导购网站域名信息查询系统

怎么做导购网站,域名信息查询系统,公司注册网站查询,做网站填写主要品牌怎么填写文章目录 前言一、锁1.定义一个锁变量2.pthread_mutex_init3.pthread_mutex_destroy4.pthread_mutex_lock/pthread_mutex_unlock5.静态变量锁和全局变量锁的初始化 二、问题描述及锁的运用三、RAII风格的锁 前言 临界资源: 在多个线程或进程间共享的资源. 临界区: 代码中访问临…

文章目录

  • 前言
  • 一、锁
    • 1.定义一个锁变量
    • 2.pthread_mutex_init
    • 3.pthread_mutex_destroy
    • 4.pthread_mutex_lock/pthread_mutex_unlock
    • 5.静态变量锁和全局变量锁的初始化
  • 二、问题描述及锁的运用
  • 三、RAII风格的锁


前言

临界资源: 在多个线程或进程间共享的资源.
临界区: 代码中访问临界资源的那部分代码区域.
多个线程同时访问共享数据, 其中至少一个线程进行了写操作, 且没有适当的同步机制来保护数据, 可能导致数据的不一致性, 也就是一种线程安全问题.

一、锁

多个线程同时访问共享数据, 其中至少一个线程进行了写操作, 且没有适当的同步机制来保护数据, 可能导致数据的不一致性, 对于这种问题, 可以通过加锁来解决, 加锁后, 只有申请到锁的线程才能进入临界区执行代码语句, 其他没有竞争到锁的线程会阻塞等待, 直到申请到锁的线程将锁释放, 接着各个线程再来竞争锁.
相当于被加锁的代码区域只能被各个线程串行执行.

1.定义一个锁变量

头文件: #include <pthread.h>

pthread_mutex_t mutex;

2.pthread_mutex_init

头文件: #include <pthread.h>
函数声明: int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);

  • 返回值: 如果成功, 返回值为 0, 如果失败, 返回一个非零错误码.
  • mutex: 指向要初始化的互斥锁的指针.
  • attr: 设置互斥锁的属性, 一般传递 nullptr, 表示使用默认属性.

功能: 初始化锁.

示例代码:

pthread_mutex_t mutex;
pthread_mutex_init(&mutex, nullptr);

3.pthread_mutex_destroy

头文件: #include <pthread.h>
函数声明: int pthread_mutex_destroy(pthread_mutex_t *mutex);

  • 返回值: 如果成功, 返回值为 0, 如果失败, 返回一个非零错误码.
  • mutex: 指向要释放的互斥锁的指针.

功能: 释放锁.

示例代码:

pthread_mutex_t mutex;
pthread_mutex_destroy(&mutex);

4.pthread_mutex_lock/pthread_mutex_unlock

头文件: #include <pthread.h>
函数声明: int pthread_mutex_lock(pthread_mutex_t *mutex); / int pthread_mutex_unlock(pthread_mutex_t *mutex);

  • 返回值: 如果成功, 返回值为 0, 如果失败, 返回一个非零错误码.
  • mutex: 指向已初始化的互斥锁的指针.

功能: 加锁/解锁.

示例代码:

pthread_mutex_t mutex;
pthread_mutex_init(&mutex, nullptr);
pthread_mutex_lock(&mutex);
//...
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);

在 pthread_mutex_lock(&mutex); 和 pthread_mutex_unlock(&mutex); 之间的代码就是被加锁的代码, 只有申请到锁的线程才能进入执行, 释放锁后, 各个线程再重新竞争锁.

5.静态变量锁和全局变量锁的初始化

如果锁变量是 static 修饰的静态变量锁或者是声明在全局的锁, 可以直接通过宏进行初始化:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

二、问题描述及锁的运用

假设多个线程的入口函数为同一个, 代码如下:

#include <iostream>
#include <pthread.h>
using namespace std;void* Routine(void* arg)
{int cnt = 0;for(int i = 0; i < 3; ++i){printf("线程[%lld]中的cnt: %d, 地址为: 0x%x\n", pthread_self(), ++cnt, &cnt);}cout << endl;
}int main()
{pthread_t tids[3];for(int i = 0; i < 3; ++i){pthread_create(tids + i, nullptr, Routine, nullptr);}for(int i = 0; i < 3; ++i){pthread_join(tids[i], nullptr);}return 0;
}

可以看到, 在入口函数中, 存在一个变量 cnt, 那么多个线程的入口函数都是同一个, 每个线程都对该入口函数里的 cnt 进行累加操作, 是否会出现线程安全问题呢?

运行结果:
在这里插入图片描述
这里是不存在线程安全问题的, 因为每个线程在线程库中都存在自己的结构及数据上下文:
在这里插入图片描述
所以在入口函数中的变量等数据都是每个线程私有的一部分, 因此并不会有线程安全问题.

但是如果是全局变量或者被 static 修饰的变量, 被多个线程同时访问修改时就会存在线程安全问题, 假设一个场景: 三个线程进行"抢票", 即对全局变量 tickets 进行减减操作, 代码如下:

#include <iostream>
#include <cstdio>
#include <unistd.h>
#include <pthread.h>
using namespace std;int tickets = 30; //总票数void* Ticket(void* arg)
{while(1){//还有票if(tickets > 0){usleep(100000); //休眠0.1秒,模拟抢票前戏printf("线程 0x%x 抢到了一张票,还剩 %d 张票...\n", pthread_self(), --tickets);}else{break;}}return nullptr;
}int main()
{pthread_t tids[3];for(int i = 0; i < 3; ++i){pthread_create(tids + i, nullptr, Ticket, nullptr);}for(int i = 0; i < 3; ++i){pthread_join(tids[i], nullptr);}return 0;
}

运行结果:
在这里插入图片描述
可以看到, 在不加锁的情况下, tickets 直接被干到负数了, 原因就在于当 tickets 只剩 1 张时, 进行 if(tickets > 0) 判断时, 三个线程并行的执行了判断且进入了 if 语句内, 那 tickets 被干到负数也是必然的了.

通过加锁来规避这个问题, 代码修改如下:

#include <iostream>
#include <cstdio>
#include <unistd.h>
#include <pthread.h>
using namespace std;int tickets = 10000; //总票数
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;void* Ticket(void* arg)
{while(1){pthread_mutex_lock(&mutex);//还有票if(tickets > 0){usleep(50000); //休眠0.05秒,模拟抢票前戏printf("线程 0x%x 抢到了一张票,还剩 %d 张票...\n", pthread_self(), --tickets);pthread_mutex_unlock(&mutex);}else{pthread_mutex_unlock(&mutex);break;}}return nullptr;
}int main()
{pthread_t tids[3];for(int i = 0; i < 3; ++i){pthread_create(tids + i, nullptr, Ticket, nullptr);}for(int i = 0; i < 3; ++i){pthread_join(tids[i], nullptr);}pthread_mutex_destroy(&mutex);return 0;
}

需要注意的是 if 和 else 语句中都需要进行解锁, 如果只在 if 中解锁, 最后申请到锁但走了 else 语句的线程就并没有释放锁, 可能导致其他在等待锁资源的线程永远阻塞申请不到锁.

运行结果:
在这里插入图片描述

三、RAII风格的锁

虽然加锁, 解锁配套使用不难, 但毕竟是人写的, 难免可能出现加锁后忘了解锁, 而后导致死锁的情况, 所以通过 RAII 设计风格封装一下锁的使用, 可以有效避免这种问题.

示例代码:

#include <iostream>
#include <cstdio>
#include <unistd.h>
#include <pthread.h>
using namespace std;int tickets = 100; //总票数
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;class LockGuard 
{
public://构造加锁LockGuard(pthread_mutex_t* m): _pmutex(m){pthread_mutex_lock(_pmutex);}//析构解锁~LockGuard (){pthread_mutex_unlock(_pmutex);}
public:pthread_mutex_t* _pmutex;
};void* Ticket(void* arg)
{while(1){usleep(100000);LockGuard lg(&mutex);//还有票if(tickets > 0){usleep(50000); //休眠0.05秒,模拟抢票前戏printf("线程 0x%x 抢到了一张票,还剩 %d 张票...\n", pthread_self(), --tickets);}else{break;}}return nullptr;
}int main()
{pthread_t tids[3];for(int i = 0; i < 3; ++i){pthread_create(tids + i, nullptr, Ticket, nullptr);}for(int i = 0; i < 3; ++i){pthread_join(tids[i], nullptr);}pthread_mutex_destroy(&mutex);return 0;
}

运行结果:
在这里插入图片描述
这样可以达到, 构造时加锁, 析构时解锁, 全自动化, 不必担心忘了解锁了.

http://www.dt0577.cn/news/27659.html

相关文章:

  • 做网站的费用seo搜索引擎优化推荐
  • 上海seo整站优化深圳设计公司
  • 网站制作模板程序福建省人民政府门户网站
  • 有没关于做动画设计师的网站武汉网络营销公司排名
  • 微商自己做网站肇庆seo按天收费
  • 旅业认证二维码有什么用成都网站优化排名推广
  • 做诈骗网站seo网络推广案例
  • 无锡做网站设计搜索引擎广告优化
  • 湖南省建设监理协会官网哈尔滨seo推广优化
  • 在线做任务的网站外贸营销网站制作
  • 网站开发常用小图片站长素材网
  • 设计网站卖钱广州谷歌推广
  • 游戏网址站长seo
  • 专业网站建设收费公司模板建站
  • 政府网站排版企业建站
  • 做喷绘可以在那个网站找app开发费用一览表
  • myeclipse做网站哪里可以学网络运营和推广
  • 怎么做祝福的网站什么是搜索关键词
  • wordpress拿站chrome手机版
  • 网站建设规划方案.ppt网站建设与管理
  • 郑州直播网站建设公司广告推广一个月多少钱
  • wordpress如何打开数据库上海seo推广平台
  • 日本的网页建设网站百度seo按天计费
  • 河西网站建设开发seo排名推广
  • 湖南 网站备案百度小程序对网站seo
  • 网站版权该怎么做呢百度账号批发网
  • 企业网站维护怎么做搜索引擎大全排行
  • 做网站最基础需要什么条件武汉百度搜索优化
  • 百度网站怎样做推广永久免费的培训学校管理软件
  • 网站如何做背景音乐百度图片搜索引擎