并发编程实战笔记

并发编程实战笔记

并行累加求和

template<class Iterator, class T>//Iterator 迭代器类型,T 内置数据类型
accumulate_block(Iterator first, Iterator last, T& result) {
    result = accumulate(first, last, result);
}

template<class Iterator, class T>
T parallel_accumulate(Iterator first, Iterator last, T init) {
    const unsigned long length = std::distance(first, last);//distance 求迭代器间距离
    if (!length) return init;
    const unsigned long min_per_thread = 25;
    const unsigned long max_threads = (length + min_per_thread - 1) / min_per_thread;
    const unsigned long hardware_threads = thread::hardware_concurrency();//cpu支持线程并发数
    const unsigned long num_threads = min(hardware_threads != 0 ? hardware_threads : 2, max_threads);
    const unsigned long block_size = length / num_threads;

    vector<T> results(num_threads);
    vector<thread> threads(num_threads - 1);//加上当前线程 凑够num_threads

    Iterator block_start = first;
    for (unsigned long i = 0; i < (num_threads - 1); i++) {
        Iterator block_end = block_start;
        advance(block_end, block_size);
        threads[i] = thread(accumulate_block<Iterator, T>, block_start, block_end, ref(results[i]));
        block_start = block_end;
    }
    accumulate_block(block_start, last, results[num_threads - 1]);
    for_each(threads.begin(),threads.end(),mem_fn(&thread::join));//阻塞等待线程结束
    return std::accumulate(results.begin(), results.end(), init);//累加个线程结果并返回
}

int main() {
    vector<int> vi;
    for (int i = 0; i < 48516; i++) {
        vi.push_back(10);
    }
    int sum = parallel_accumulate(vi.begin(), vi.end(), 5);//accumulate形参:首指针,尾指针,初始值
    cout << "sum = " << sum << endl;
    return EXIT_SUCCESS;
}

数据共享

三种方式实现数共享:

  1. 有锁保护,对数据结构采用某种保护机制,确保只有进行修改的线程才能看到不变量被破坏时的中间状态。
  2. 无锁保护,对数据结构和不变量的设计进行修改,修改完的结构必须能完成一系列不可分割的变化,也就是保证每个不变量保持稳定的状态,这就是所谓的无锁编程。
  3. 事务形式,所需的一些数据和读取都存储在事务日志中,然后将之前的操作合为一步,再进行提交。

避免死锁的建议

  1. 使用固定顺序获取锁:
    在每个线程上,让两个互斥量总以相同的顺序上锁。
  2. 同时获取所有资源,std::lock要么锁住所有资源,要么一个都不锁。
  3. 避免嵌套锁:一个线程已获得一个锁时,别再去获取第二个。
  4. 避免在持有锁时调用用户提供的代码:
    在持有锁的情况下调用用户代码,而用户代码中可能有获取其他锁的操作。
  5. 使用锁的层次结构:
    当代码试图对一个互斥量上锁,在该层锁已被底层持有时,上锁是不允许的。

保护很少更新的数据结构

这里需要另一种不同的互斥量,这种互斥量常被称为“读者-作者锁”,因为其允许两种不同的使用方式:
一个“作者”线程独占访问和共享访问,让多个“读者”线程并发访问。

对于更新操作,可以使用 std::lock_guard<boost::shared_mutex>std::unique_lock<boost::shared_mutex> 上锁。作为 std::mutex 的替代方案,与 std::mutex 所做的一样,这就能保证更新线程的独占访问。因为其他线程不需要去修改数据结构,所以其可以使用 boost::shared_lock<boost::shared_mutex> 获取访问权。

update_or_add_entry()函数调用时,独占锁会阻止其他线程对数据结构进行修改,并且阻止线程调用find_entry()

class dns_cache
{
    std::map<std::string,dns_entry> entries;
    boost::shared_mutex entry_mutex;
public:
    dns_entry find_entry(std::string const& domain)
    {
        boost::shared_lock<boost::shared_mutex> lk(entry_mutex);
        std::map<std::string,dns_entry>::const_iterator const it=
            entries.find(domain);
        return (it==entries.end())?dns_entry():it->second;
    }
    void update_or_add_entry(std::string const& domain,
                             dns_entry const& dns_details)
    {
        std::lock_guard<boost::shared_mutex> lk(entry_mutex);
        entries[domain]=dns_details;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nehzil-kino

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值