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

三亚住房和城乡建设厅网站织梦网站背景

三亚住房和城乡建设厅网站,织梦网站背景,什么秀网站做效果图,培训网站大数据分析目录 1.引言 2.std::atomic 支持的复杂类型 3.std::atomic与无锁 4.如何使用 std::atomic 保护复杂类型 4.1.使用互斥锁(Mutex) 4.2.使用 std::atomic_flag 和自旋锁 4.3.原子共享指针(Atomic Shared Pointers) 4.4.使用高…

目录

1.引言

2.std::atomic 支持的复杂类型

3.std::atomic与无锁

4.如何使用 std::atomic 保护复杂类型

4.1.使用互斥锁(Mutex)

4.2.使用 std::atomic_flag 和自旋锁

4.3.原子共享指针(Atomic Shared Pointers)

4.4.使用高级同步机制

5.std::atomic 和 volatile 的区别

6.总结


1.引言

        std::atomic 是 C++11 标准库中的一个模板类,用于提供原子操作。原子操作是不可分割的操作,即在多线程环境下执行时,不会被线程调度机制打断。这保证了在多线程编程中,对共享数据的访问是安全的,避免了数据竞争和不一致性问题。

        std::atomic 可以用于基本数据类型,如整型(intlongbool 等)和指针类型。它提供了一套成员函数,用于执行原子读、写、交换、比较并交换等操作。如:

 

#include <iostream>
#include <atomic>
#include <thread>std::atomic<int> counter(0);void increment() {for (int i = 0; i < 1000; ++i) {++counter;}
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Final counter value: " << counter << std::endl;return 0;
}

        std::atomic 还可以用于更复杂的类型,如自定义类和结构体,但使用复杂类型时有一些额外的限制和注意事项。

2.std::atomic 支持的复杂类型

C++11 标准引入了对复杂类型的原子支持,但需要满足以下条件:

必须是“平凡可复制”的类型

  • 只有**平凡可复制(Trivially Copyable)**的类型才能直接用于 std::atomic

  • 平凡可复制的含义:

    • 没有自定义的构造函数、析构函数、拷贝构造和拷贝赋值运算符。

    • 可以通过 memcpy 直接拷贝的类型。

C++之std::is_trivially_copyable(平凡可复制类型检测)_trivially copyable-CSDN博客

        示例如下:

#include <atomic>
#include <iostream>
#include <thread>struct Point {int x;int y;
};std::atomic<Point> point = Point{0, 0};void modify_point() {Point p = point.load();p.x += 1;p.y += 1;point.store(p);
}int main() {std::thread t1(modify_point);std::thread t2(modify_point);t1.join();t2.join();Point p = point.load();std::cout << "Point: (" << p.x << ", " << p.y << ")\n";return 0;
}

输出:

Point: (2, 2) 

解释: 

  • Point 是一个平凡可复制的类型,因此可以直接用 std::atomic<Point>

  • 由于原子性操作是对整个结构体进行的,但这里存在竞态条件,fetch_add 不适用于结构体。

不支持的类型示例(非平凡可复制):

#include <atomic>
#include <iostream>
#include <thread>struct Person {std::string name;int age;
};std::atomic<Person> person = Person{"Alice", 30}; // ❌ 编译错误int main() {return 0;
}

报错原因:

  • std::string 是一个复杂类型,包含动态内存分配,因此不是平凡可复制的类型。

3.std::atomic与无锁

   std::atomic<T>一定是无锁的吗?其实只要你花一点时间去翻一下cppreference.com就能得到答案:“不!”,因为std::atomic<T>提供了一个方法叫is_lock_free

        考虑以下几个结构体:

struct A { long x; };
struct B { long x; long y; };
struct C { char s[1024]; };

        A应当是无锁的,因为它显然等价于long。C应该不是无锁的,因为它实在是太大了,目前没有寄存器能存下它。至于B我们就很难直接推断出来了。

        对于x86架构的CPU,结构体B应当是无锁的,它刚刚好可以原子地使用MMX寄存器(64bit)处理。但如果它再大一点(比如塞一个int进去),它就不能无锁地处理了。

        原子操作究竟是否无锁与CPU的关系很大。如果CPU提供了丰富的用于无锁处理的指令与寄存器,则能够无锁执行的操作就会多一些,反之则少一些。除此之外,原子操作能否无锁地执行还与内存对齐有关。正因如此,is_lock_free()才会是一个运行时方法,而没有被标记为constexpr

4.如何使用 std::atomic 保护复杂类型

4.1.使用互斥锁(Mutex)

使用互斥锁(如 std::mutex)来保护对复杂类型数据的访问。这是最常见的方法,可以确保在任何时候只有一个线程可以访问数据。

#include <iostream>
#include <thread>
#include <mutex>struct ComplexType {int a;double b;std::string c;
};ComplexType data;
std::mutex dataMutex;void modifyData(int newA, double newB, const std::string& newC) {std::lock_guard<std::mutex> lock(dataMutex);data.a = newA;data.b = newB;data.c = newC;
}void printData() {std::lock_guard<std::mutex> lock(dataMutex);std::cout << "a: " << data.a << ", b: " << data.b << ", c: " << data.c << std::endl;
}int main() {std::thread t1(modifyData, 10, 20.5, "Hello");std::thread t2(printData);t1.join();t2.join();return 0;
}

4.2.使用 std::atomic_flag 和自旋锁

对于复杂类型,可以使用原子标志位实现自旋锁,保护整个临界区。

#include <atomic>
#include <iostream>
#include <thread>struct Person {std::string name;int age;
};Person person = {"Alice", 30};
std::atomic_flag lock_flag = ATOMIC_FLAG_INIT;void lock() {while (lock_flag.test_and_set(std::memory_order_acquire)) {} // 自旋等待
}void unlock() {lock_flag.clear(std::memory_order_release);
}void update_person() {lock();person.age += 1;std::cout << "Updated Age: " << person.age << "\n";unlock();
}int main() {std::thread t1(update_person);std::thread t2(update_person);t1.join();t2.join();std::cout << "Final Age: " << person.age << "\n";return 0;
}

解释:

  • 使用了 std::atomic_flag 实现了一个简单的自旋锁,保护了对 Person 结构体的访问。

  • 由于 std::string 是非平凡可复制类型,这里需要使用自旋锁来保护。

4.3.原子共享指针(Atomic Shared Pointers)

C++11 中,std::atomic 还支持 std::shared_ptr,用于管理对象的引用计数。这种技术特别适合实现并发的数据结构,避免对象的过早销毁或误用。

#include <atomic>
#include <memory>
#include <iostream>struct ComplexData {int value1;double value2;std::string value3;ComplexData(int v1, double v2, std::string v3): value1(v1), value2(v2), value3(v3) {}
};std::atomic<std::shared_ptr<ComplexData>> dataPtr;void updateData(int v1, double v2, const std::string& v3) {// 为新数据创建一个shared_ptrstd::shared_ptr<ComplexData> newData = std::make_shared<ComplexData>(v1, v2, v3);// 原子地替换旧数据std::atomic_store(&dataPtr, newData);
}void processData() {// 原子地读取共享指针std::shared_ptr<ComplexData> data = std::atomic_load(&dataPtr);if (data) {std::cout << "Current Data: " << data->value1 << ", " << data->value2 << ", " << data->value3 << std::endl;} else {std::cout << "Data pointer is null." << std::endl;}
}int main() {updateData(10, 20.5, "Test Data");processData();return 0;
}

在这个代码中:

  • ComplexData 结构体用于存储一个整数、一个双精度浮点数和一个字符串。
  • dataPtr 是一个原子性的 std::shared_ptr<ComplexData>,用于确保对复杂数据的线程安全访问。
  • updateData 函数创建一个新的 ComplexData 实例,并原子性地替换旧数据。
  • processData 函数原子性地读取数据并打印。

这样,即使在多线程环境中,对 dataPtr 的访问也是安全的,避免了数据竞争的问题。

4.4.使用高级同步机制

对于更复杂的同步需求,你可以考虑使用条件变量(std::condition_variable)、信号量(std::binary_semaphore,C++20 引入)等高级同步机制。

5.std::atomic 和 volatile 的区别

许多人常常混淆 std::atomic 和 volatile。二者在多线程中的作用非常不同:

  • volatile 只是告诉编译器不要对其进行优化,适用于处理与硬件相关的操作,无法保证线程安全。
  • std::atomic 是多线程同步原语,保证原子性和线程安全,适合多线程编程。
  • volatile int counter = 0;  // 不安全,不能用于多线程
    std::atomic<int> atomic_counter = 0;  // 线程安全

6.总结

        std::atomic 提供轻量、高效的原子操作,适用于不需要复杂锁机制的场景。同时需理解内存顺序对性能和正确性的影响。对于复杂的多操作组合,仍需谨慎处理竞态条件。不当使用 load 和 store 导致竞态条件、对内存顺序的误解、复合操作的不原子性。

参考:

https://en.cppreference.com/w/cpp/atomic/atomic


文章转载自:

http://vP7ZzXAk.crkhd.cn
http://ol9S5NlK.crkhd.cn
http://UZ2eQeLd.crkhd.cn
http://6Azxhwah.crkhd.cn
http://KuJjmuiK.crkhd.cn
http://vMWxNBSh.crkhd.cn
http://n0j22ZIL.crkhd.cn
http://QDUNW8UI.crkhd.cn
http://c418RowW.crkhd.cn
http://mEMrv09p.crkhd.cn
http://PBjmEuel.crkhd.cn
http://lioz2rjl.crkhd.cn
http://18SnrX82.crkhd.cn
http://6RpQMcfi.crkhd.cn
http://Z6Tod0bN.crkhd.cn
http://Js350SAZ.crkhd.cn
http://LpXvdXQG.crkhd.cn
http://Ejskte5H.crkhd.cn
http://MUFlZIow.crkhd.cn
http://cgpHXALr.crkhd.cn
http://5MN3JqP5.crkhd.cn
http://s7QICZFM.crkhd.cn
http://W7bZXTFv.crkhd.cn
http://ufzNRTFg.crkhd.cn
http://TOjbGG6Z.crkhd.cn
http://EoXwRXmD.crkhd.cn
http://HZInq1Go.crkhd.cn
http://q2rLt0g5.crkhd.cn
http://iqKwfrLM.crkhd.cn
http://kyqplubR.crkhd.cn
http://www.dtcms.com/wzjs/624057.html

相关文章:

  • 永久免费网站空间旅游公网站如何做
  • 网站平台推广旅游网站开发分析报告
  • 网站建设具备哪些技术人员狮城app更多网站
  • php网站的部署在线图片制作生成
  • 网站悬浮框代码阿里指数查询官网
  • 企业网站建设的目的有()1688做网站难吗
  • 单位网站建设服务域名备案未及时注销处罚
  • 百度对网站的收录网站建设及外包
  • 手机访问网站跳wap北京做网站哪家好
  • wordpress建站时间科普网站建设
  • 海宁网站建设童程童美少儿编程怎样收费
  • 免费建立网站软件商城系统 wordpress嵌入
  • 个人网站推广方法国内十大游戏公司排名
  • 怎样用模板做网站那类型网站容易做排名
  • 手机网站meta国内旅行做行程网站
  • 定制网站开发哪家好智能获客系统
  • 门户网站改版东莞常平有高铁站吗
  • wordpress gitignore网页优化包括
  • 昆明做网站找哪个公司好百度平台商家app下载
  • 北京国贸网站建设如何修改网站元素
  • 烟台市城市建设发展有限公司网站要建网站
  • 网站建设 qq业务网制作网站建设协议需要注意的问题
  • 网站上的菠菜游戏哪里可以做代码给wordpress添加图片
  • 网站设计常用软件都有哪些互联网推广开户
  • wordpress建站云盘服务类型网站开发需要哪些技术
  • 建网站费用 优帮云天津网站建设论坛
  • 学校网站建设考评办法网站制作价格服务
  • 湖南做网站的公司有哪些有网站模板怎么建站
  • 濮阳高端网站建设平面设计有什么网站
  • 网站网页设计怎样园林景观设计公司管理流程