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

wordpress网站都有哪些绍兴百度seo排名

wordpress网站都有哪些,绍兴百度seo排名,史志网站建设必要性,石家庄市住房和城乡建设委员会网站在Qt的多线程编程中,有时用到原子变量类型QAtomicInt,与C原生的std::atomic类似,优点是:可以确保对象只有一个;缺点是:对象的状态,在不同的内存模型/线程中,有不同的状态的&#xff…

    在Qt的多线程编程中,有时用到原子变量类型QAtomicInt,与C++原生的std::atomic类似,优点是:可以确保对象只有一个;缺点是:对象的状态,在不同的内存模型/线程中,有不同的状态的,需要做同步操作。
    原子变量的同步操作,既可以借助锁、信号量、临界区等额外变量来实现,也可以原子变量自身的CAS方法,来做同步。
    这里介绍原子变量的CAS写法,比如,下面第1节代码A,是一个无锁队列,采用QAtomiInt+QSemaphore实现。其中,入队函数是put(const Pancake& pancake), 出队函数是take()。
    这里的put(const Pancake& pancake)函数,采用了CAS方法,实现m_tail变量,在多个线程里的状态同步,即在线程ThreadA里看到m_tail值,与线程ThreadB里看到的m_tail值是一致的。

1 无锁队列-- 代码A

    下面是一个C++编写的无锁队列。

// 1)煎饼类
class Pancake {
public:Pancake(int id) : m_id(id) {}int getId() const { return m_id; }private:int m_id;
};// 2) 无锁队列
class PancakeTray_LockFree_WithSemaphore {
public:PancakeTray_LockFree_WithSemaphore(int capacity = 5) : m_capacity(capacity + 1), m_buffer(capacity + 1) {m_head = 0;m_tail = 0;m_notFull = new QSemaphore(capacity);   // 控制容量m_notEmpty = new QSemaphore(0);         // 控制可用项数量}~PancakeTray_LockFree_WithSemaphore() {delete m_notFull;delete m_notEmpty;}void put(const Pancake& pancake) {m_notFull->acquire();  // 等待空位,避免忙等// 无锁获取写入位置int currentTail;int nextTail;do {currentTail = m_tail;nextTail = (currentTail + 1) % m_capacity;} while (!m_tail.testAndSetOrdered(currentTail, nextTail));// 写入数据m_buffer[currentTail] = pancake;qDebug() << QString("师傅制作了煎饼#%1,托盘上现有%2个煎饼").arg(pancake.getId()).arg(getCount());m_notEmpty->release(); // 通知有新项可用}Pancake take() {m_notEmpty->acquire(); // 等待可用项,避免忙等// 无锁获取读取位置int currentHead;int nextHead;do {currentHead = m_head;nextHead = (currentHead + 1) % m_capacity;} while (!m_head.testAndSetOrdered(currentHead, nextHead));// 读取数据Pancake pancake = m_buffer[currentHead];m_notFull->release();  // 通知有新空位return pancake;}int getCount() const {int head = m_head;int tail = m_tail;return (tail - head + m_capacity) % m_capacity;}private:QVector<Pancake> m_buffer;int m_capacity;QAtomicInt m_head;QAtomicInt m_tail;QSemaphore* m_notFull;QSemaphore* m_notEmpty;
};

2 CAS方法

    我们已经知道,put()函数,属于入队操作,其代码如下:

    void put(const Pancake& pancake) {m_notFull->acquire();  // 等待空位,避免忙等// 无锁获取写入位置int currentTail;int nextTail;do {currentTail = m_tail;nextTail = (currentTail + 1) % m_capacity;} while (!m_tail.testAndSetOrdered(currentTail, nextTail));// 写入数据m_buffer[currentTail] = pancake;qDebug() << QString("师傅制作了煎饼#%1,托盘上现有%2个煎饼").arg(pancake.getId()).arg(getCount());m_notEmpty->release(); // 通知有新项可用}

    那么,put()函数里,“do{} while(m_tail.testAndSetOrdered(currentTail, nextTail))” 的作用是啥?

    这是一个很好的问题!下面,详细解释这个do-while循环的作用和原理。

2.1 问题分析

    这段代码的作用是原子性地获取并更新写入位置,它解决了多线程环境下的竞态条件问题。

do {currentTail = m_tail;                    // 1. 读取当前尾指针nextTail = (currentTail + 1) % m_capacity; // 2. 计算下一个位置
} while (!m_tail.testAndSetOrdered(currentTail, nextTail)); // 3. 原子性比较并交换

2.2 状态更新,为什么需要循环?

    由于是多线程操作这个无锁队列,即至少有2个以上线程,来执行put()函数。为了描述方便,这里只考虑2个线程的情况:线程A、线程B;
    场景如下:

初始状态:m_tail = 2线程A                    线程B
------                   ------
currentTail = 2          currentTail = 2     ← 都读到相同值
nextTail = 3             nextTail = 3        ← 都计算出相同的下一位置testAndSetOrdered(2,3)   testAndSetOrdered(2,3)
返回 true ✓              返回 false ✗        ← 只有一个能成功!

2.3 testAndSetOrdered()函数的工作原理

bool testAndSetOrdered(int expectedValue, int newValue)

    testAndSetOrdered()函数,执行一个原子操作,即要么操作成功,要么操作失败,
    若操作成功,则更新值;若操作失败,则使用原来的值;
具体如下:

  • 1 比较:检查当前值是否等于expectedValue
  • 2 交换:如果相等,设置为newValue
  • 3 返回:返回操作是否成功
    关键特性:整个过程是原子的,不可被打断!

2.4 循环的作用

    在put()函数里的do{}while循环,反复执行testAndSetOrdered()函数,确保多个线程里的m_tail值,都是相同的;若不相同,则m_tail.testAndSetOrdered()返回false,又会进入循环,直到m_tail.testAndSetOrdered()返回true,即m_tail在所有的线程里都更新了。

do {currentTail = m_tail;                    // 重新读取最新值nextTail = (currentTail + 1) % m_capacity;
} while (!m_tail.testAndSetOrdered(currentTail, nextTail)); // 失败就重试

    执行流程如下:

  • 1)第一次尝试:如果没有竞争,直接成功退出;
  • 2)失败重试:如果其他线程修改了m_tail,重新读取最新值并再次尝试;
  • 3)最终成功:直到成功获取到独占的写入位置;

    具体如下:

初始:m_tail = 2时刻1:
线程A: currentTail=2, nextTail=3, testAndSetOrdered(2,3) → 成功,m_tail变为3
线程B: currentTail=2, nextTail=3, testAndSetOrdered(2,3) → 失败(m_tail已经是3了)时刻2:
线程B: 重新读取 currentTail=3, nextTail=4, testAndSetOrdered(3,4) → 成功,m_tail变为4

2.4 为啥不能用原子变量++或–

    如果用原子自身的++:

// ❌ 错误的做法
int pos = m_tail++;  // 不是原子操作!

    会导致如下异常:
-1)数据竞争:多个线程可能得到相同的位置(自减不降,导致数据没有出队);
-2)数据丢失:两个线程写入同一位置(自增覆盖,导致数据没有入队);
-3)缓冲区损坏:指针状态不一致;

2.5 CAS方法的优缺点

    CAS方法的全称:Compare And Swap,具体如下:

  • Compare:比较当前值
  • And:如果相等
  • Swap:交换为新值

优势:
✅ 无需锁,性能高
✅ 避免死锁
✅ 线程安全

缺点:
⚠️ 在高竞争下可能重试多次
⚠️ 实现复杂度较高

    这就是为什么无锁编程既强大又复杂的原因!
    这个do-while循环是确保线程安全的关键机制。

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

相关文章:

  • 买的虚拟主机怎么做网站5118
  • 个性网站模版seo排名技术教程
  • 陵水网站建设咨询热门推广软件
  • 怎样做网站变手机软件广州aso优化
  • 我想做网站怎么做百度相册登录入口
  • 网站的反链怎么做百度数据研究中心官网
  • 已购买域名 如何做网站知乎软文推广
  • 广西 网站开发seo研究中心道一老师
  • 网页设计作品点评苏州seo安严博客
  • 哪里有做网站app的肇庆seo排名
  • 开发平台教程西安搜索引擎优化
  • 做企业网站域名需要解析吗软文平台
  • 网站建设类文章技师培训
  • 夸克作文网站制作网站软件
  • 网站内容如何编辑吉林seo网络推广
  • 做译员的网站我赢网客服系统
  • 网页设计实训总结万能版1000字网站推广的优化
  • 企业手机端网站源码天津百度推广代理商
  • 临沂网站群发软件模板网站免费
  • c sql网站开发海外销售平台有哪些
  • 五合一网站建设黑马程序员培训机构在哪
  • 找网站设计百度图片识别在线使用
  • 中纪委网站作风建设在路上视频网站推广
  • 做那个的网站谁有长春网长春关键词排名站设计
  • 网站建设前期如何规划网站建设公司业务
  • 北京网站建设多少钱网站收录查询爱站
  • wordpress主题怎么安装seo简介
  • 一般的手机网站建设多少钱app推广平台接单渠道
  • 做好网站建设工作二级域名注册平台
  • 网络培训心得体会5篇四川seo整站优化费用