托管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线程池的更多相关文章

  1. 线程锁的本质:线程控制、线程状态控制 while if:根据线程的关系(模式)协调线程的执行

    线程锁的本质:线程控制.线程状态控制 while if https://www.cnblogs.com/feng9exe/p/8319000.html https://www.cnblogs.com/ ...

  2. Linux同步机制(一) - 线程锁

    1 互斥锁 在线程实际运行过程中,我们经常需要多个线程保持同步. 这时可以用互斥锁来完成任务.互斥锁的使用过程中,主要有 pthread_mutex_init pthread_mutex_destor ...

  3. 多线程(五) java的线程锁

    在多线程中,每个线程的执行顺序,是无法预测不可控制的,那么在对数据进行读写的时候便存在由于读写顺序多乱而造成数据混乱错误的可能性.那么如何控制,每个线程对于数据的读写顺序呢?这里就涉及到线程锁. 什么 ...

  4. 关于Unity中协程、多线程、线程锁、www网络类的使用

    协程 我们要下载一张图片,加载一个资源,这个时候一定不是一下子就加载好的,或者说我们不一定要等它下载好了才进行其他操作,如果那样的话我就就卡在了下载图片那个地方,傻住了.我们希望我们只要一启动加载的命 ...

  5. 【C#】为什么有可能会被多个线程修改的对象要加线程锁

    例1.不用线程锁的情况下,两个线程对同一个变量进行加减操作 static void Main(string[] args) { Counter counter = new Counter(); var ...

  6. 托管C++线程锁实现

    最近由于工作需要,开始写托管C++,由于C++11中的mutex,和future等类,托管C++不让调用(报错),所以自己实现了托管C++的线程锁. 该类可确保当一个线程位于代码的临界区时,另一个线程 ...

  7. c++11多线程---线程锁(mutex)

    #include<mutex> 包含四类锁: 1      std::mutex    最基本也是最常用的互斥类 2      std::recursive_mutex  同一线程内可递归 ...

  8. APUE学习笔记——11 线程同步、互斥锁、自旋锁、条件变量

    线程同步     同属于一个进程的不同线程是共享内存的,因而在执行过程中需要考虑数据的一致性.     假设:进程有一变量i=0,线程A执行i++,线程B执行i++,那么最终i的取值是多少呢?似乎一定 ...

  9. day9---多线程,线程锁,队列

    进程.线程 http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html 使用threading模块实现多线程编程[综述] Pyt ...

随机推荐

  1. charsets - 程序员对字符集和国际化的观点

    描述 Linux 是一个国际性的操作系统.它的各种各样实用程序和设备驱动程序 (包括控制台驱动程序 ) 支持多种语言的字符集,包括带有附加符号的拉丁字母表字符,重音符,连字(字母结合), 和全部非拉丁 ...

  2. 对散列进行sort排序,只是会产生一个顺序,但这顺序和初始化时的顺序不一致

    109 my $slice_layouts;    110 my $vertical_assignment;    111 my %map_function_indices = (    112    ...

  3. 用宿主机创建一个容器bind命令的应用

    先创建一个网页目录 [root@docker ~]# mkdir /app/wwwroot -p 用bind运行,源目录为刚才创建的 [root@docker ~]# docker run -itd ...

  4. Android图像处理之Bitmap类(1)

    Bitmap是Android系统中的图像处理的最重要类之一.用它可以获取图像文件信息,进行图像剪切.旋转.缩放等操作,并可以指定格式保存图像文件.本文从应用的角度,着重介绍怎么用Bitmap来实现这些 ...

  5. oracle分配权限 学习笔记--转载

    在全局数据库ORCL下创建一个用户首先在开始-->运行——>sqlplus,然后输入 sys/change_on_install as sysdba 以sys权限登陆进去 然后可以进行操作 ...

  6. WC2007 石头剪刀布 数学+最小费用最大流

    题面: 有N个人参加一场比赛,赛程规定任意两个人之间都要进行一场比赛:这样总共有N*(N-1)/2场比赛.比赛已经进行了一部分,我们想知道在极端情况下,比赛结束后最多会发生多少剪刀石头布情况.即给出已 ...

  7. 零基础入门学习Python(1)--我和Python的第一次亲密接触

    前言 最近在学习Python编程语言,于是乎就在网上找资源.其中小甲鱼<零基础入门学习Python>试听了几节课,感觉还挺不错,里面的视频都是免费下载,小甲鱼讲话也挺幽默风趣的,所以呢,就 ...

  8. PHP实现定时任务的几种方式

    关于定时任务,之前以前认识了一种最常用的:crontab定时任务.通过linux的定时任务去实现.今天又认识了一下php实现定时方式的其它方式,总结一下. 一 服务器定时任务 服务器定时任务,其实就是 ...

  9. 如何转成libsvm支持的数据格式并做回归分析

    本次实验的数据是来自老师给的2006-2008年的日期,24小时的温度.电力负荷数据,以及2009年的日期,24小时的温度数据,目的是预测2009年每天24小时的电力负荷,实验数据本文不予给出. 用l ...

  10. java读utf8 的txt文件,第一个字符为空或问号问题

    参考:https://blog.csdn.net/yangzhichao888/article/details/79529756 https://blog.csdn.net/wangzhi291/ar ...