托管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 ...
随机推荐
- ssh设置免秘钥登录
系统:CentOS7.2 需求:A服务器的fab用户需要使用www用户免秘钥登录到B服务器 换句话说,就是在A服务器的fab用户下,ssh www@B服务ip -p 端口 ,然后登录过去 ...
- R-FCN:Object Detection via Region-based Fully Convolutional Networks
fast.faster这些网络都可以被roi-pooling层分成两个子网络:1.a shared,'fully convolutional' subnetwork 2.an roi-wise sub ...
- joda-time时间操作组件
今天看到了学习到了一个不错的操作时间的jar包,很方便的,以后操作时间运算就可以直接使用jar包中的方法了,再也不用自己写操作时间的方法了.懒的不行不行的 <!-- 时间操作组件 --> ...
- Windows——bat中的路径和工具栏运行bat的坑
工具栏添加的批处理环境 编写一个简单的批处理文件 set testEnv = %cd% pause 这里第一句:设置当前文件夹路径为环境变量testEnv的值 这里第二句:暂停命令窗口 第一次我们直接 ...
- U盘启动盘制作工具(安装Linux)
2018-09-15 17:36:42 1. Etcher 官网:https://etcher.io/ 资料来源:https://linuxmint-installation-guide.readt ...
- Buffer.concat()
Buffer.concat(list[, totalLength]) Node.js FS模块方法速查 list {Array} 需要连接的 Buffer 对象数组 totalLength {Numb ...
- [bzoj1058][ZJOI2007][报表统计] (STL)
Description 小Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工 作,作为她的生日礼物之一.经过仔细观察,小Q发现统计一张报表实际上是维护一个 ...
- ASP.NET MVC的帮助类HtmlHelper和UrlHelper
在ASP.NET MVC框架中没有了自己的控件,页面显示完全就回到了写html代码的年代.还好在asp.net mvc框架中也有自带的HtmlHelper和UrlHelper两个帮助类.另外在MvcC ...
- node学习的一些网站
Node.js 包教不包会 篇幅比较少 node express 入门教程 nodejs定时任务 一个nodejs博客 [NodeJS 学习笔记04]新闻发布系统 过年7天乐,学nodejs 也快乐 ...
- python接口自动化测试(一)
本节开始,开始介绍python的接口自动化测试,首先需要搭建python开发环境,到https://www.python.org/下载python 版本直接安装就以了,建议 下载python2.7.1 ...