#include <iostream>
#include <thread>
#include <deque>
#include <functional>
#include <future>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <memory>
#include <chrono>

class ZYLThreadPool {
public:
    ZYLThreadPool(size_t minThreads = 20, size_t maxThreads = 200)
        : _minThreads(minThreads)
        , _maxThreads(maxThreads)
        , _stop(false) {
        worker_threads.reserve(_maxThreads);
        for (size_t i = 0; i < _minThreads; ++i) {
            create_thread();
        }
    }

    void create_thread() {
        worker_threads.emplace_back([this] {
            for (;;) {
                std::function<void()> task;
                {
                    std::unique_lock<std::mutex> lock(this->_mutex);
                    this->_condVar.wait(lock, [this] {
                        return this->_stop || !this->_taskQueue.empty();
                    });
                    if (this->_stop && this->_taskQueue.empty())
                        return;
                    task = std::move(this->_taskQueue.front());
                    this->_taskQueue.pop_front();
                }
                task();
            }
        });
    }

    template <typename F, typename... Args>
    auto submit(F&& f, Args&&... args)-> std::future<typename std::result_of<F(Args...)>::type> {
        using return_type = typename std::result_of<F(Args...)>::type;

        auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));

        std::future<return_type> result = task->get_future();
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if (_stop) {
                throw std::runtime_error("Submit on stopped ZYLThreadPool");
            }
            if (_taskQueue.size() >= worker_threads.size() && worker_threads.size() < _maxThreads) {
                create_thread();
            }
            _taskQueue.emplace_back([task] { (*task)(); });
        }
        _condVar.notify_one();
        return result;
    }

    void cancel() {
        std::unique_lock<std::mutex> lock(_mutex);
        if (!_stop) {
            _stop = true;
            _condVar.notify_all();
        }
        for (std::thread& worker : worker_threads)
            worker.join();
    }

    size_t getNumTasks() {
        std::unique_lock<std::mutex> lock(_mutex);
        return _taskQueue.size();
    }

    ~ZYLThreadPool() {
        cancel();
    }

private:
    std::vector<std::thread> worker_threads;
    std::deque<std::function<void()>> _taskQueue;
    size_t _minThreads;
    size_t _maxThreads;
    std::mutex _mutex;
    std::condition_variable _condVar;
    bool _stop;
};

class Test {
public:
    Test(double devid)
        : _devid(devid)
        , _running(true) {
    }

    void start(ZYLThreadPool& threadPool) {
        _future = threadPool.submit(&Test::_task, this);
    }

    void stop() {
        {
            _running = false;
            std::unique_lock<std::mutex> lock(_mutex);

            if (_future.valid()) {
                _future.get();
                lock.unlock();
                _cleanupResources();
            }
        }
    }

private:
    std::mutex _mutex;
    double _devid;
    std::deque<double> _dequeue_packets;
    std::future<void> _future;
    bool _running;

    void _cleanupResources() {
        std::unique_lock<std::mutex> lock(_mutex);
        _dequeue_packets.clear();
    }

    void _task() {
        std::unique_lock<std::mutex> lock(_mutex);
        while (_running) {
            if (_dequeue_packets.empty()) {
                //std::cout << "running task"<< std::endl;
                continue;
            }
            double packet = _dequeue_packets.front();
            _dequeue_packets.pop_front();
            lock.unlock();
            std::cout << "running task" << std::endl;
            lock.lock();
        }
		std::cout<<"task end"<<std::endl;
    }
};

int main() {
    ZYLThreadPool zylThreadPool(20, 200);
    std::vector<std::shared_ptr<Test>> tests;
	std::cout<<"start all task"<<std::endl;
    for (int i = 0; i < 100; ++i) {
        auto test = std::make_shared<Test>(1.0);
        test->start(zylThreadPool);
        tests.push_back(test);
    }

    std::this_thread::sleep_for(std::chrono::seconds(3));
	std::cout<<"stop all task"<<std::endl;
    for (auto& test : tests) {
        test->stop();
    }
    tests.clear();
	std::cout<<"start 3 task"<<std::endl;
	
    for (int i = 0; i < 3; ++i) {
        auto test = std::make_shared<Test>(1.0);
        test->start(zylThreadPool);
        tests.push_back(test);
    }

    std::this_thread::sleep_for(std::chrono::seconds(5));
	std::cout<<"stop 3 task"<<std::endl;
    for (auto& test : tests) {
        test->stop();
    }
	std::cout<<"stop 3 task end"<<std::endl;
	while(1){
		std::this_thread::sleep_for(std::chrono::seconds(3));
	}

    return 0;
}
问题：上面例子出现了死锁
1.开启100个任务，能无阻塞启动，此时的线程数是97
2.停止100个任务，出现死锁，此时的线程数还是97
请修复