托管C++线程锁实现 c++11线程池
托管C++线程锁实现
最近由于工作需要,开始写托管C++,由于C++11中的mutex,和future等类,托管C++不让调用(报错),所以自己实现了托管C++的线程锁。
该类可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区。 如果其他线程尝试进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。
1 using namespace System; 2 using namespace System::Threading; 3 4 ref class Lock 5 { 6 public: 7 Lock(Object ^ pObject) 8 : m_pObject(pObject) 9 { 10 Monitor::Enter(m_pObject); 11 } 12 13 ~Lock() 14 { 15 Monitor::Exit(m_pObject); 16 } 17 18 private: 19 Object ^ m_pObject; 20 };
注:原则上m_pObject是可以为任意类型,但是String是一个例外。
String也是应用类型,从语法上来说是没有错的。
但是锁定字符串尤其危险,因为字符串被公共语言运行库 (CLR)“暂留”。 这意味着整个程序中任何给定字符串都只有一个实例,就是这同一个对象表示了所有运行的应用程序域的所有线程中的该文本。因此,只要在应用程序进程中的任何位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。通常,最好避免锁定 public 类型或锁定不受应用程序控制的对象实例。例如,如果该实例可以被公开访问,则 lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象。这可能导致死锁,即两个或更多个线程等待释放同一对象。出于同样的原因,锁定公共数据类型(相比于对象)也可能导致问题。而且lock(this)只对当前对象有效,如果多个对象之间就达不到同步的效果。lock(typeof(Class))与锁定字符串一样,范围太广了。
c++11线程池
1 #pragma once 2 3 #include <future> 4 5 #include <vector> 6 7 #include <atomic> 8 9 #include <queue> 10 11 #include <thread> 12 13 #include <mutex> 14 15 namespace std { 16 17 //线程池最大容量,应尽量设小一点 18 #define THREADPOOL_MAX_NUM 16 19 20 class ThreadPool 21 { 22 public: 23 ThreadPool(unsigned short size = 1) { AddThread(size); } 24 ~ThreadPool() 25 { 26 if (_run.load()) 27 { 28 Close(); 29 } 30 } 31 32 void Close() 33 { 34 _run.store(false); 35 //唤醒所有线程执行 36 _task_cv.notify_all(); 37 for (thread &th : _pool) 38 { 39 if (th.joinable()) 40 th.join(); 41 } 42 } 43 44 //提交一个任务, 45 template<class F, class... Args> 46 auto commit(F&& f, Args&&... args) ->future<decltype(f(args...))> 47 { 48 if (!_run) 49 throw runtime_error("commit on ThreadPool is stop."); 50 // typename std::result_of<F(Args...)>::type, 函数 f 的返回值类型 51 using RetType = decltype(f(args...)); 52 //把函数入口及参数打包 53 auto task = make_shared<packaged_task<RetType()>>(bind(forward<F>(f), forward<Args>(args)...)); 54 55 future<RetType> future = task->get_future(); 56 { 57 lock_guard<mutex> lock{ _lock }; 58 _tasks.emplace([task]() {(*task)(); }); 59 } 60 #ifdef THREADPOOL_AUTO_GROW if (_id1ThrNum < 1 && _pool.size() < THREADPOOL_MAX_NUM) AddThread(1); #endif _task_cv.notify_one(); return future; } 61 62 int IdlCount() { return _id1ThrNum; } 63 int BusyCount() { return _pool.size(); } 64 65 void AddThread(unsigned short size) 66 { 67 for (; _pool.size() < THREADPOOL_MAX_NUM && size > 0; --size) 68 { 69 _pool.emplace_back([this] { 70 while (_run.load()) 71 { 72 Task task; 73 { 74 unique_lock<mutex> lock{ _lock }; 75 _task_cv.wait(lock, [this] 76 { 77 return !_run.load() || !_tasks.empty(); 78 }); 79 if (!_run.load() && _tasks.empty()) 80 return; 81 task = move(_tasks.front()); 82 _tasks.pop(); 83 } 84 _id1ThrNum--; 85 task(); 86 _id1ThrNum++; 87 } 88 }); 89 _id1ThrNum--; 90 } 91 } 92 93 public: 94 //定义类型 95 using Task = std::function<void()>; 96 //线程池 97 vector<thread> _pool; 98 //锁 99 mutex _lock; 100 //任务队列 101 queue<Task> _tasks; 102 //条件阻塞 103 condition_variable _task_cv; 104 //线程是否在执行 105 atomic<bool> _run{ true }; 106 //空闲线程 107 atomic<int> _id1ThrNum{ 0 }; 108 }; 109 }
托管C++线程锁实现 c++11线程池的更多相关文章
- 线程锁的本质:线程控制、线程状态控制 while if:根据线程的关系(模式)协调线程的执行
线程锁的本质:线程控制.线程状态控制 while if https://www.cnblogs.com/feng9exe/p/8319000.html https://www.cnblogs.com/ ...
- Linux同步机制(一) - 线程锁
1 互斥锁 在线程实际运行过程中,我们经常需要多个线程保持同步. 这时可以用互斥锁来完成任务.互斥锁的使用过程中,主要有 pthread_mutex_init pthread_mutex_destor ...
- 多线程(五) java的线程锁
在多线程中,每个线程的执行顺序,是无法预测不可控制的,那么在对数据进行读写的时候便存在由于读写顺序多乱而造成数据混乱错误的可能性.那么如何控制,每个线程对于数据的读写顺序呢?这里就涉及到线程锁. 什么 ...
- 关于Unity中协程、多线程、线程锁、www网络类的使用
协程 我们要下载一张图片,加载一个资源,这个时候一定不是一下子就加载好的,或者说我们不一定要等它下载好了才进行其他操作,如果那样的话我就就卡在了下载图片那个地方,傻住了.我们希望我们只要一启动加载的命 ...
- 【C#】为什么有可能会被多个线程修改的对象要加线程锁
例1.不用线程锁的情况下,两个线程对同一个变量进行加减操作 static void Main(string[] args) { Counter counter = new Counter(); var ...
- 托管C++线程锁实现
最近由于工作需要,开始写托管C++,由于C++11中的mutex,和future等类,托管C++不让调用(报错),所以自己实现了托管C++的线程锁. 该类可确保当一个线程位于代码的临界区时,另一个线程 ...
- c++11多线程---线程锁(mutex)
#include<mutex> 包含四类锁: 1 std::mutex 最基本也是最常用的互斥类 2 std::recursive_mutex 同一线程内可递归 ...
- APUE学习笔记——11 线程同步、互斥锁、自旋锁、条件变量
线程同步 同属于一个进程的不同线程是共享内存的,因而在执行过程中需要考虑数据的一致性. 假设:进程有一变量i=0,线程A执行i++,线程B执行i++,那么最终i的取值是多少呢?似乎一定 ...
- day9---多线程,线程锁,队列
进程.线程 http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html 使用threading模块实现多线程编程[综述] Pyt ...
随机推荐
- 去掉PhpStorm打开自动启动的项目
有时候启动的项目很大,导致很卡,而且在编辑器中更改也没效果,简单暴力的办法 找到项目的目录,删除其中的.idea文件夹
- Bullet:MySQL增强半同步参数rpl_semi_sync_master_wait_point值AFTER_SYNC和AFTER_COMMIT的对比实验
MySQL 5.7.22启用增强半同步复制 MySQL对该参数值的描述 Semisync can wait for slave ACKs at one of two points, AFTER_SYN ...
- 专题训练——[kuangbin带你飞]最短路练习
最短路练习 0. Til the Cows Come Home POJ - 2387 完美的模板题 //#include<Windows.h> #include<iostream& ...
- NOIP专题复习1 图论-最短路
一.知识概述 今天我们要复习的内容是图论中的最短路算法,我们在这里讲3种最短路求法,分别是:floyd,dijkstra,spfa. 那么我们从几道例题来切入今天讲解的算法. 二.典型例题 1.热浪 ...
- String与常量池(JDK1.8)
---- 基础知识 String是final类, 并且其方法都被final修饰 String通过char数组来保存字符串 对String对象的任何操作都不会影响到原来的String对象, 所有的改变都 ...
- 【spring】jar包详解与模块依赖关系
以spring3.X为例 jar包详解 1. spring-core.jar:包含Spring框架基本的核心工具类,Spring其它组件要都要使用到这个包里的类,是其它组件的基本核心: 2. spri ...
- 安装lnmp
一.yum安装php 1.更新更新yum源:rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rp ...
- OpenCV+Python实现视频文件裁剪功能
Python编程实现对视频文件进行剪切的功能.截取指定长度的视频并保存,运行后首先选择要裁剪的视频,然后输入开始时间点和停止时间点即可.将剪切后的视频保存为output.avi文件 所属网站分类: 资 ...
- LeetCode(29)Divide Two Integers
题目 Divide two integers without using multiplication, division and mod operator. If it is overflow, r ...
- [bzoj3531][Sdoi2014][旅行] (主席树+树链剖分)
Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. ...