托管C++线程锁实现

 

最近由于工作需要,开始写托管C++,由于C++11中的mutex,和future等类,托管C++不让调用(报错),所以自己实现了托管C++的线程锁。

该类可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区。 如果其他线程尝试进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。

  1. 1 using namespace System;
  2. 2 using namespace System::Threading;
  3. 3
  4. 4 ref class Lock
  5. 5 {
  6. 6 public:
  7. 7 Lock(Object ^ pObject)
  8. 8 : m_pObject(pObject)
  9. 9 {
  10. 10 Monitor::Enter(m_pObject);
  11. 11 }
  12. 12
  13. 13 ~Lock()
  14. 14 {
  15. 15 Monitor::Exit(m_pObject);
  16. 16 }
  17. 17
  18. 18 private:
  19. 19 Object ^ m_pObject;
  20. 20 };

注:原则上m_pObject是可以为任意类型,但是String是一个例外。

String也是应用类型,从语法上来说是没有错的。

但是锁定字符串尤其危险,因为字符串被公共语言运行库 (CLR)“暂留”。 这意味着整个程序中任何给定字符串都只有一个实例,就是这同一个对象表示了所有运行的应用程序域的所有线程中的该文本。因此,只要在应用程序进程中的任何位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。通常,最好避免锁定 public 类型或锁定不受应用程序控制的对象实例。例如,如果该实例可以被公开访问,则 lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象。这可能导致死锁,即两个或更多个线程等待释放同一对象。出于同样的原因,锁定公共数据类型(相比于对象)也可能导致问题。而且lock(this)只对当前对象有效,如果多个对象之间就达不到同步的效果。lock(typeof(Class))与锁定字符串一样,范围太广了。

c++11线程池

 
  1. 1 #pragma once
  2. 2
  3. 3 #include <future>
  4. 4
  5. 5 #include <vector>
  6. 6
  7. 7 #include <atomic>
  8. 8
  9. 9 #include <queue>
  10. 10
  11. 11 #include <thread>
  12. 12
  13. 13 #include <mutex>
  14. 14
  15. 15 namespace std {
  16. 16
  17. 17 //线程池最大容量,应尽量设小一点
  18. 18 #define THREADPOOL_MAX_NUM 16
  19. 19
  20. 20 class ThreadPool
  21. 21 {
  22. 22 public:
  23. 23 ThreadPool(unsigned short size = 1) { AddThread(size); }
  24. 24 ~ThreadPool()
  25. 25 {
  26. 26 if (_run.load())
  27. 27 {
  28. 28 Close();
  29. 29 }
  30. 30 }
  31. 31
  32. 32 void Close()
  33. 33 {
  34. 34 _run.store(false);
  35. 35 //唤醒所有线程执行
  36. 36 _task_cv.notify_all();
  37. 37 for (thread &th : _pool)
  38. 38 {
  39. 39 if (th.joinable())
  40. 40 th.join();
  41. 41 }
  42. 42 }
  43. 43
  44. 44 //提交一个任务,
  45. 45 template<class F, class... Args>
  46. 46 auto commit(F&& f, Args&&... args) ->future<decltype(f(args...))>
  47. 47 {
  48. 48 if (!_run)
  49. 49 throw runtime_error("commit on ThreadPool is stop.");
  50. 50 // typename std::result_of<F(Args...)>::type, 函数 f 的返回值类型
  51. 51 using RetType = decltype(f(args...));
  52. 52 //把函数入口及参数打包
  53. 53 auto task = make_shared<packaged_task<RetType()>>(bind(forward<F>(f), forward<Args>(args)...));
  54. 54
  55. 55 future<RetType> future = task->get_future();
  56. 56 {
  57. 57 lock_guard<mutex> lock{ _lock };
  58. 58 _tasks.emplace([task]() {(*task)(); });
  59. 59 }
  60. 60 #ifdef THREADPOOL_AUTO_GROW if (_id1ThrNum < 1 && _pool.size() < THREADPOOL_MAX_NUM) AddThread(1); #endif _task_cv.notify_one(); return future; }
  61. 61
  62. 62 int IdlCount() { return _id1ThrNum; }
  63. 63 int BusyCount() { return _pool.size(); }
  64. 64
  65. 65 void AddThread(unsigned short size)
  66. 66 {
  67. 67 for (; _pool.size() < THREADPOOL_MAX_NUM && size > 0; --size)
  68. 68 {
  69. 69 _pool.emplace_back([this] {
  70. 70 while (_run.load())
  71. 71 {
  72. 72 Task task;
  73. 73 {
  74. 74 unique_lock<mutex> lock{ _lock };
  75. 75 _task_cv.wait(lock, [this]
  76. 76 {
  77. 77 return !_run.load() || !_tasks.empty();
  78. 78 });
  79. 79 if (!_run.load() && _tasks.empty())
  80. 80 return;
  81. 81 task = move(_tasks.front());
  82. 82 _tasks.pop();
  83. 83 }
  84. 84 _id1ThrNum--;
  85. 85 task();
  86. 86 _id1ThrNum++;
  87. 87 }
  88. 88 });
  89. 89 _id1ThrNum--;
  90. 90 }
  91. 91 }
  92. 92
  93. 93 public:
  94. 94 //定义类型
  95. 95 using Task = std::function<void()>;
  96. 96 //线程池
  97. 97 vector<thread> _pool;
  98. 98 //锁
  99. 99 mutex _lock;
  100. 100 //任务队列
  101. 101 queue<Task> _tasks;
  102. 102 //条件阻塞
  103. 103 condition_variable _task_cv;
  104. 104 //线程是否在执行
  105. 105 atomic<bool> _run{ true };
  106. 106 //空闲线程
  107. 107 atomic<int> _id1ThrNum{ 0 };
  108. 108 };
  109. 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. createdb - 创建一个新的 PostgreSQL 数据库

    SYNOPSIS createdb [ option...] [ dbname] [ description] DESCRIPTION 描述 createdb 创建一个新的 PostgreSQL 数据 ...

  2. Vue beaforeCreate时获取data中的数据

    异步获取即:通过    $this.$nextTick或者settimeout,这连dom都可以拿出来 beforeCreate() { this.$nextTick(function() { con ...

  3. python练习2 购物车程序

    # -*- coding: utf-8 -*-# @Time : 2018/10/18 16:06# @Author : Two Brother# @EMAIL : yeluyide@163.com# ...

  4. C# 后台调用存储过程

    例一丶返回集合 [WebMethod] public object RegisterMethod(string type, string username, string password, stri ...

  5. Elasticsearch入门和基本使用

    1. 什么是Elasticsearch? Elasticsearch,分布式,高性能,高可用,可伸缩的搜索和分析系统:Elastic 是 Lucene 的封装,提供了 REST API 的操作接口,开 ...

  6. 【thinking in java】ArrayList源码分析

    简介 ArrayList底层是数组实现的,可以自增扩容的数组,此外它是非线程安全的,一般多用于单线程环境下(Vector是线程安全的,所以ArrayList 性能相对Vector 会好些) Array ...

  7. SQL中带有NOT IN 子查询改写

    报表程序中的一段SQL运行很慢,代码如下: 优化前: 耗时:1337s INSERT INTO PER_LTE_ZIB_PB_COMMISSION_07 SELECT P.TOPACTUALID, Q ...

  8. MySQL Connector/Python 接口 (三)

    本文参见这里. 使用缓冲的 cursor,下例给从2000年加入公司并且还在公司的员工薪水从明天起加15% from __future__ import print_function from dec ...

  9. sort 结构体 正数负数分开排序

    对于结构体排序的一点点记录,之前遇到过结构体排序,个人比较喜欢使用在结构体当中直接重载小于号的方法, 例如说: struct Node{ int index; int del; bool operat ...

  10. ..net 3.5新特性之用this关键字为类添加扩展方法

    具体用法如下: public static class ClassHelper { //用this 声明将要吧这个方法附加到Student对象 public static bool CheckName ...