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

济南网站制作企业phpstudy搭建本地网站

济南网站制作企业,phpstudy搭建本地网站,资讯网站开发需求,有趣的网站设计如何让一个类作为可调用对象,被 std::thread 调用 在 C 中,可以让一个类对象作为可调用对象(Callable Object),然后用 std::thread 进行调用。要实现这一点,主要有三种方法: 重载 operator()&…

如何让一个类作为可调用对象,被 std::thread 调用

在 C++ 中,可以让一个类对象作为可调用对象(Callable Object),然后用 std::thread 进行调用。要实现这一点,主要有三种方法:

  1. 重载 operator()(仿函数)
  2. 使用成员函数
  3. 使用 std::bindstd::function

1. 方法一:重载 operator()(仿函数)

最常见的方式是定义一个仿函数(functor),即重载 operator() 使类的实例可直接调用。

示例

#include <iostream>
#include <thread>class CallableObject {
public:void operator()() {  // 让对象像函数一样调用std::cout << "Thread running with CallableObject\n";}
};int main() {CallableObject obj;std::thread t(obj);  // 直接将对象传给 std::threadt.join();return 0;
}

解析

  • CallableObject 重载了 operator(),因此它的实例 obj 可以像函数一样被调用。
  • std::thread 可以直接接受 obj 作为参数,调用 operator()
  • 线程执行 obj.operator()(),输出:
    Thread running with CallableObject
    

2. 方法二:使用类的成员函数

可以直接用类的成员函数作为 std::thread 的目标,但要注意非静态成员函数需要绑定对象

示例

#include <iostream>
#include <thread>class Worker {
public:void run() {  // 成员函数std::cout << "Thread running with member function\n";}
};int main() {Worker worker;std::thread t(&Worker::run, &worker);  // 传递成员函数指针和对象t.join();return 0;
}

解析

  • &Worker::runWorker成员函数指针
  • &worker 传入对象指针,std::thread 需要对象来调用成员函数
  • 线程执行 worker.run(),输出:
    Thread running with member function
    

3. 方法三:使用 std::bind 绑定成员函数

如果 std::thread 需要额外的参数,可以用 std::bindstd::function 绑定成员函数和对象。

示例

#include <iostream>
#include <thread>
#include <functional>class Worker {
public:void run(int x) {std::cout << "Thread running with parameter: " << x << "\n";}
};int main() {Worker worker;std::thread t(std::bind(&Worker::run, &worker, 42));  // 绑定成员函数和参数t.join();return 0;
}

解析

  • std::bind(&Worker::run, &worker, 42) 绑定 worker.run(42)
  • std::thread 线程启动后会执行 worker.run(42)
  • 输出:
    Thread running with parameter: 42
    

4. 方法四:使用 std::function 结合 Lambda

另一种方式是用 std::function 存储可调用对象(比如 Lambda 或仿函数),然后传给 std::thread

示例

#include <iostream>
#include <thread>
#include <functional>class Worker {
public:void run(int x) {std::cout << "Thread running with parameter: " << x << "\n";}
};int main() {Worker worker;std::function<void()> func = std::bind(&Worker::run, &worker, 42);std::thread t(func);t.join();return 0;
}

解析

  • std::function<void()> 存储 worker.run(42)
  • std::thread 线程执行 func()
  • 输出:
    Thread running with parameter: 42
    

5. 选择哪种方式?

方法特点适用场景
仿函数(operator())直接使用对象,无需额外绑定线程对象无需额外参数
成员函数需要对象指针才能调用适用于普通类成员函数
std::bind 绑定成员函数允许传递额外参数需要动态传递参数时
std::function结合 std::bind,适用于通用接口适用于异步任务调度

对于简单任务,建议使用 重载 operator()。对于需要参数的任务,建议使用 std::bindstd::function


6. 组合使用:多个线程调用类对象

可以创建多个线程,并让它们执行类中的函数:

#include <iostream>
#include <thread>
#include <vector>class Worker {
public:void run(int id) {std::cout << "Thread " << id << " is running\n";}
};int main() {Worker worker;std::vector<std::thread> threads;for (int i = 0; i < 5; ++i) {threads.emplace_back(&Worker::run, &worker, i);}for (auto& t : threads) {t.join();}return 0;
}

输出

Thread 0 is running
Thread 1 is running
Thread 2 is running
Thread 3 is running
Thread 4 is running

总结

  • 让类成为可调用对象的常见方式:
    1. 仿函数(重载 operator()
    2. 成员函数(使用 &Class::method, &object 绑定)
    3. 使用 std::bind() 绑定成员函数
    4. 使用 std::function 存储可调用对象
  • 推荐用法
    • 简单的可调用对象仿函数
    • 普通成员函数std::thread t(&Class::method, &object)
    • 需要传参的成员函数std::bindstd::function
    • 多个线程调用同一个对象std::vector<std::thread>

多个线程调用同一个对象 ➝ std::vector<std::thread>

在 C++ 多线程编程中,我们经常希望多个线程同时调用同一个对象的成员函数。这通常用于:

  • 并行计算(多个线程操作同一个数据对象)
  • 任务调度(多个线程调用同一个处理对象)
  • 服务器/多客户端模型(多个线程访问同一个服务器对象)

使用 std::vector<std::thread> 可以创建多个线程,并让它们调用同一个对象的成员函数


1. 示例:多个线程调用同一个对象的成员函数

#include <iostream>
#include <thread>
#include <vector>class Worker {
public:void doWork(int id) {std::cout << "Thread " << id << " is working\n";}
};int main() {Worker worker;  // 所有线程共享这个对象std::vector<std::thread> threads;for (int i = 0; i < 5; ++i) {threads.emplace_back(&Worker::doWork, &worker, i);}for (auto& t : threads) {t.join();}return 0;
}

可能的输出(线程执行顺序可能不同):

Thread 0 is working
Thread 1 is working
Thread 2 is working
Thread 3 is working
Thread 4 is working

2. 代码解析

  1. 创建 Worker 对象

    Worker worker;
    
    • 这里 worker所有线程共享的对象
  2. 使用 std::vector<std::thread> 管理多个线程

    std::vector<std::thread> threads;
    
    • std::vector<std::thread> 存储多个 std::thread 对象,避免单独管理多个线程对象。
  3. 创建多个线程并调用 worker.doWork(i)

    for (int i = 0; i < 5; ++i) {threads.emplace_back(&Worker::doWork, &worker, i);
    }
    
    • &Worker::doWork:获取 Worker 类的成员函数指针。
    • &worker:传入对象指针,确保 doWorkworker 对象上调用。
    • i:传入线程的 ID,作为参数。
  4. 等待所有线程完成

    for (auto& t : threads) {t.join();
    }
    
    • 遍历 threads,对每个线程调用 join(),确保主线程等待所有子线程完成。

3. 线程安全问题

如果 Worker 类的 doWork 方法修改了成员变量,可能会发生数据竞争(Race Condition)。

示例:线程不安全

#include <iostream>
#include <thread>
#include <vector>class Worker {
private:int counter = 0;  // 共享变量public:void doWork(int id) {++counter;  // 线程不安全std::cout << "Thread " << id << " incremented counter to " << counter << "\n";}
};int main() {Worker worker;std::vector<std::thread> threads;for (int i = 0; i < 5; ++i) {threads.emplace_back(&Worker::doWork, &worker, i);}for (auto& t : threads) {t.join();}return 0;
}

可能的错误输出

Thread 0 incremented counter to 1
Thread 1 incremented counter to 2
Thread 2 incremented counter to 3
Thread 3 incremented counter to 2  // ❌ 竞争导致错误
Thread 4 incremented counter to 5

问题:

  • 多个线程同时修改 counter,导致数据竞争(Race Condition)。
  • 线程 3 可能在 counter = 2 之前读取旧值,导致计数错误。

4. 解决方案:使用 std::mutex 保护数据

使用 std::mutex 保护 counter,防止数据竞争。

#include <iostream>
#include <thread>
#include <vector>
#include <mutex>class Worker {
private:int counter = 0;std::mutex mtx;  // 互斥锁public:void doWork(int id) {std::lock_guard<std::mutex> lock(mtx);  // 加锁++counter;std::cout << "Thread " << id << " incremented counter to " << counter << "\n";}
};int main() {Worker worker;std::vector<std::thread> threads;for (int i = 0; i < 5; ++i) {threads.emplace_back(&Worker::doWork, &worker, i);}for (auto& t : threads) {t.join();}return 0;
}

输出

Thread 0 incremented counter to 1
Thread 1 incremented counter to 2
Thread 2 incremented counter to 3
Thread 3 incremented counter to 4
Thread 4 incremented counter to 5

修改点

  • 使用 std::mutex 互斥锁,防止多个线程同时访问 counter
  • std::lock_guard<std::mutex> 自动管理锁,避免手动 lock() / unlock()

5. 结论

  • 多个线程可以调用同一个对象的成员函数,可以使用 std::vector<std::thread> 统一管理线程。
  • 如果成员函数只读,不修改成员变量,线程是安全的。
  • 如果成员函数修改成员变量,必须使用 std::mutex 保护数据,防止数据竞争(Race Condition)。
  • std::vector<std::thread> 让多个线程的管理更加方便,避免单独管理多个 std::thread 变量。

这种模式在多线程服务器、任务分发、并行计算等场景非常常见。


文章转载自:

http://9f99HkTH.tdppt.cn
http://tcL8y8Pe.tdppt.cn
http://Kq4HczyU.tdppt.cn
http://FvzbdFzA.tdppt.cn
http://OjWDqX04.tdppt.cn
http://0cU9t2TF.tdppt.cn
http://e8qz48ms.tdppt.cn
http://ZUXVjX9V.tdppt.cn
http://UZeSnPS2.tdppt.cn
http://J3h7LKvG.tdppt.cn
http://StQ6XbTK.tdppt.cn
http://hMmnVp2K.tdppt.cn
http://aBgVawms.tdppt.cn
http://EAFkNhqm.tdppt.cn
http://YggSo5Iv.tdppt.cn
http://kgOqjgw3.tdppt.cn
http://2hRIQeJJ.tdppt.cn
http://kbYlwyy2.tdppt.cn
http://ScFN4XkG.tdppt.cn
http://BztDOAxE.tdppt.cn
http://DEAClpuN.tdppt.cn
http://PUumENrS.tdppt.cn
http://WuLabVBV.tdppt.cn
http://BHWMoG8z.tdppt.cn
http://rPUOW6z3.tdppt.cn
http://5Te1lYUQ.tdppt.cn
http://QUPgv0xF.tdppt.cn
http://Lyo0tXQS.tdppt.cn
http://MqSqgAxF.tdppt.cn
http://hciKvUH3.tdppt.cn
http://www.dtcms.com/wzjs/758195.html

相关文章:

  • 兰州网站建设 冰雨网页设计培训评价怎么写
  • 平度168网站建设移动互联网 传统网站
  • 网站购买空间信阳百度推广公司电话
  • 网站适配手机怎么做网站怎么做双机房切换
  • 电商网站建设价格低wordpress更改邮箱
  • 网站建设个人职责网络推广专员是干嘛的
  • 网站建设的经济可行性分析网络营销策略ppt
  • 某个网站做拍卖预展的好处廊坊seo建站
  • h5做的分销网站网页访问自动跳转中
  • 如何使用上线了app建设网站vs2008 手机网站开发
  • 网站建设结构分布网络培训课堂app
  • 动漫网站建设总结网站做seo
  • wordpress 外贸站主题网页设计制作网站素材
  • 做技术一般逛那些网站黄山地区建设行业网站
  • 网站管理后台文章排序百度招聘平台
  • 实业有限公司网站怎么做wordpress企业建
  • seo网站建设方案以数字域名为网址的网站
  • 做电脑网站步骤seo课程培训学校
  • 揭阳模板建站开发公司网络营销工具与方法
  • 建设公司与建筑公司的区别上海哪学网站建设优化
  • 音乐网站可以用什么语言做电子商务网站建设成都
  • 手机网站做静态路径网站开发工具
  • 网站制作怎样容易新密做网站公司
  • 做招聘网站需要人力资源许可外贸网站有什么
  • 个人做网站的流程外贸网站有哪些平台
  • 云建网站网址做网站效果
  • 云主机建网站做娃衣的布料去哪个网站
  • 潍坊网站制作维护建站系统cms
  • 在什么网站做外贸潍坊市房屋和城乡建设局网站
  • 网络文化经营许可证怎么办杭州seo托管公司推荐