并发编程(6)基于锁的并发数据结构设计

主要内容:

  • 并发数据结构设计的意义
  • 指导如何设计
  • 实现为并发设计的数据结构

  如果一种数据结构可以被多个线程所访问,其要不就是绝对不变的(其值不会发生变化,
并且不需同步),要不程序就要对数据结构进行正确的设计,以确保其能在多线程环境下能够
(正确的)同步。一种选择是使用独立的互斥量,其可以锁住需要保护的数据,另一种选择是设计一种能够并发访问的数据结构。第一种使用互斥量,在同一时间只有一个线程可以访问数据,实际是一种串行的序列化访问。显示的组织了多线程对数据结构的并发访问。

所以,缩小保护区域,减少序列化访问,就能提高并发。允许线程并发读取的数据结构并不少见,而对数据结构的修改,必须是单线程独立访问。所以不可能完全实现并发,只能让序列化访问最小化。

一、基于锁的并发数据结构

基于锁的并发数据结构设计,需要确保访问线程持有锁的时间最短。都是在保证数据结构是线程安全的前提下。在设计数据结构,考虑以下问题:

  • 锁的范围中的操作,是否允许在所外执行?
  • 数据结构中不同的区域是否能被不同的互斥量所保护?
  • 所有操作都需要同级互斥量保护吗?
  • 能否对数据结构进行简单的修改,以增加并发访问的概率,且不影响操作语义?

1、使用锁实现一个线程安全的栈

 1 #include <exception>
 2 struct empty_stack: std::exception
 3 {
 4   const char* what() const throw();
 5 };
 6 template<typename T>
 7 class threadsafe_stack
 8 {
 9 private:
10   std::stack<T> data;
11   mutable std::mutex m;
12 public:
13   threadsafe_stack(){}
14   threadsafe_stack(const threadsafe_stack& other)
15   {
16     std::lock_guard<std::mutex> lock(other.m);
17     data=other.data;
18   }
19   threadsafe_stack& operator=(const threadsafe_stack&) = delete;
20   void push(T new_value)
21   {
22     std::lock_guard<std::mutex> lock(m);
23     data.push(std::move(new_value)); // 1
24   }
25   std::shared_ptr<T> pop()
26   {
27      std::lock_guard<std::mutex> lock(m);
28     if(data.empty()) throw empty_stack(); // 2
29     std::shared_ptr<T> const res(
30       std::make_shared<T>(std::move(data.top()))); // 3
31     data.pop(); // 4
32     return res;
33   }
34   void pop(T& value)
35   {
36     std::lock_guard<std::mutex> lock(m);
37     if(data.empty()) throw empty_stack();
38     value=std::move(data.top()); // 5
39     data.pop(); // 6
40   }
41   bool empty() const
42   {
43     std::lock_guard<std::mutex> lock(m);
44     return data.empty();
45   }
46 };

线程安全队列——使用锁和条件变量

线程安全队列——使用细粒度锁和条件变量

(参考《并发编程》,先占坑以后补上没有实战经验看不太懂)

二、使用锁设计更加复杂的数据结构

编写一个使用锁的线程安全查询表

编写一个使用锁的线程安全链表

原文地址:https://www.cnblogs.com/huangfuyuan/p/9131666.html

时间: 2024-10-30 15:37:29

并发编程(6)基于锁的并发数据结构设计的相关文章

Java并发编程:Concurrent锁机制解析

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd

Java并发编程的艺术,解读并发编程的优缺点

并发编程的优缺点 使用并发的原因 多核的CPU的背景下,催生了并发编程的趋势,通过并发编程的形式可以将多核CPU的计算能力发挥到极致,性能得到提升. 在特殊的业务场景下先天的就适合于并发编程. 比如在图像处理领域,一张1024X768像素的图片,包含达到78万6千多个像素.即时将所有的像素遍历一边都需要很长的时间, 面对如此复杂的计算量就需要充分利用多核的计算的能力.又比如当我们在网上购物时,为了提升响应速度,需要拆分,减库存, 生成订单等等这些操作,就可以进行拆分利用多线程的技术完成. 面对复

Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型

一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例子 #并发运行,效率高,但竞争同一打印终端,带来了打印错乱 from multiprocessing import Process import os,time def work(): print('%s is running' %os.getpid()) time.sleep(2) print('

并发编程--CAS自旋锁

在前两篇博客中我们介绍了并发编程--volatile应用与原理和并发编程--synchronized的实现原理(二),接下来我们介绍一下CAS自旋锁相关的知识. 一.自旋锁提出的背景 由于在多处理器系统环境中有些资源因为其有限性,有时需要互斥访问(mutual exclusion),这时会引入锁的机制,只有获取了锁的进程才能获取资源访问.即是每次只能有且只有一个进程能获取锁,才能进入自己的临界区,同一时间不能两个或两个以上进程进入临界区,当退出临界区时释放锁.设计互斥算法时总是会面临一种情况,即

高并发编程之无锁

前几期简单介绍了一些线程方面的基础知识,以及一些线程的一些基础用法以及通过jvm内存模型的方式去介绍了一些并发中常见的问题(想看往期文章的小伙伴可以直接拉到文章最下方飞速前往).本文重点介绍一个概念“无锁” 本期精彩什么是无锁无锁类的原理AtomicIntegerUnsafeAtomicReferenceAtomicStampedReference 什么是无锁 在高并发编程中最重要的就是获取临界区资源,保证其中操作的原子性.一般来说使用synchronized关键字进行加锁,但是这种操作方式其实

[并发编程]并发编程第二篇:利用并发编程,实现计算大量数据的和

利用并发编程,实现计算大量数据的和 实现代码: package tj.pojo.generate.main; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.u

python 使用多进程实现并发编程/使用queue进行进程间数据交换

import time import os import multiprocessing from multiprocessing import Queue, pool """ 一.Python 使用多进程实现并发编程: 因为cpython解释器中有GIL存在的原因(每个进程都会维护一个GIL,jpython解释器没有这个问题),所以在一个进程内, 即使服务器是多核cpu,同一时刻只能有一个线程在执行任务(一个进程内).如果存在较多IO,使用多线程是可以提高处理速度的, 但是

高并发编程必备基础 -- 转载自 并发编程网

文章转载自 并发编程网  本文链接地址:高并发编程必备基础 一. 前言 借用Java并发编程实践中的话"编写正确的程序并不容易,而编写正常的并发程序就更难了",相比于顺序执行的情况,多线程的线程安全问题是微妙而且出乎意料的,因为在没有进行适当同步的情况下多线程中各个操作的顺序是不可预期的,本文算是对多线程情况下同步策略的一个简单介绍. 二. 什么是线程安全问题 线程安全问题是指当多个线程同时读写一个状态变量,并且没有任何同步措施时候,导致脏数据或者其他不可预见的结果的问题.Java中首

Java并发编程高阶技术 高性能并发框架源码解析与实战

第1章 课程介绍(Java并发编程进阶课程)什么是Disruptor?它一个高性能的异步处理框架,号称"单线程每秒可处理600W个订单"的神器,本课程目标:彻底精通一个如此优秀的开源框架,面试秒杀面试官.本章会带领小伙伴们先了解课程大纲与重点,然后模拟千万,亿级数据进行压力测试.让大家感性认知到Disruptor的强大.... 第2章 并发编程框架核心讲解本章带大家学习并发编程框架的基本使用与API,并介绍其内部各种组件的原理和运行机制.从而为后面的深入学习打下坚实的基础.如果对Dis