线程安全

Queue线程安全队列

自古美人都是妖i 提交于 2020-02-06 20:22:25
Python中的queue模块中提供了同步的、线程安全的队列类,包括FIFO(先进先出)队列Queue,LIFO(后入先出)队列LifoQueue。这些队列都实现了锁原语(可以理解为;原子操作,即要么不做,要么都做完),能够在多线程中直接使用。 可以使用队列来实现线程中的同步。相关函数如下: 1.初始化Queue(MaxSize):创建一个先进先出的队列; 2.qsize(): 返回队列的大小; 3.empty(): 判断队列是否为空。 4. full(): 判断队列是否满了; 5. get(): 从队列中取最后一个数据; 6.put():j将一个数据放到队列中。 示例如下: #encoding: utf-8from queue import Queueimport timeimport threadingdef set_value(q): index = 0 while True: q.put(index) index += 1 time.sleep(3)def get_value(q): while True: print(q.get())def main(): q = Queue(4) t1 = threading.Thread(target=set_value,args=[q]) t2 = threading.Thread(target=get_value,args=[q]

CAS解析

喜夏-厌秋 提交于 2020-02-06 10:51:47
CAS:compare and swap,也有的叫做 compare and set;意思都差不多,翻译过来就是比较并交换或者比较并设值。 CAS包含三个值,内存地址(V),预期值(A),新值(B)。先比较内存地址的值和预期的值是否相等,如果相等,就将新值赋在内存地址上,否则,不做任何处理。这种是乐观锁的思想。 源码解析 CAS操作在JUC中大量用到,在解析AQS那章中,我们也有提到。再回头看一下AQS中CAS的操作 protected final boolean compareAndSetState(int expect, int update) { return unsafe.compareAndSwapInt(this, stateOffset, expect, update); } 这里是对AQS中state变量进行的CAS操作,要知道,很多同步类都是通过这个变量来实现线程安全的,所以在AQS中,首先要保证对state的赋值是线程安全的。 在java中,不论什么操作,只要他还是在Java api级别,就不能保证他一定是线程安全的,除非这个操作调用系统资源来支持。这里保证state线程安全是通过unsafe中的compareAndSwapInt方法来实现的,里面的参数stateOffset就是内存地址(V),expect是预期值(A),新值(B)。在unsafe中

玩转时间操作 + 面试题

我的梦境 提交于 2020-02-06 10:01:19
玩转时间操作 + 面试题 在 JDK 8 之前,Java 语言为我们提供了两个类用于操作时间,它们分别是:java.util.Date 和 java.util.Calendar,但在 JDK 8 的时候为了解决旧时间操作类的一些缺陷,提供了几个新的类,用于操作时间和日期,它们分别是:LocalTime、LocalDateTime、Instant,都位于 java.time 包下。 时间的操作在我们日常的开发中经常见到,比如,业务数据都要记录创建时间和修改时间,并要把这些时间格式化之后显示到前端页面,再比如我们需要计算业务数据的时间间隔等,都离不开对时间的操作,那如何正确而优雅地使用时间?这就是我们接下来要讨论的话题。 时间基础知识科普 格林威治时间 格林威治(又译格林尼治)是英国伦敦南郊原格林威治天文台的所在地,它是世界计算时间和地球经度的起点,国际经度会议 1884 年在美国华盛顿召开,会上通过协议,以经过格林威治天文台的经线为零度经线(即本初子午线),作为地球经度的起点,并以格林威治为“世界时区”的起点。 格林威治时间和北京时间的关系 格林威治时间被定义为世界时间,就是 0 时区,北京是东八区。也就是说格林威治时间的 1 日 0 点,对应到北京的时间就是 1 日 8 点。 时间戳 时间戳是指格林威治时间 1970-01-01 00:00:00(北京时间 1970-01-01

多线程2--多线程带来的风险---线程安全

本秂侑毒 提交于 2020-02-05 05:17:35
1.与线程相关的栈的问题 (1)栈是用来调用方法的,局部变量在栈区,每个线程有自己的栈区,局部变量在线程之间是不能共享的。 (2)堆、常量池、方法区中的数据在线程之间是共享的。 (3)有共享数据,线程安全才能出现问题。 2.线程安全 (1)定义:如果多线程环境下代码运行的结果符合单线程环境运行的结果,则说这个程序是线程安全的。 3.线程不安全的原因 (1)线程之间交错运行; (2) 没存区域的数据不一致; 3.1.原子性(atomic)–在一段代码执行完成之前不能被中断 (1)原子性锁表现出的现象:同步互斥,表示操作是相互排斥的; (2)一条java语句不一定是原子的,也不一定只是一条指令; (3)常见的原子性表现形式: (4)不保证原子性带给多线程的问题: 如果一个线程正在对一个变量操作,中途其他线程插入进来了,如果这个操作被打断,结果就可能是错误的。 3.2.可见性(visible) (1)主内存-工作内存 来源: CSDN 作者: 以梦为马&不负韶华 链接: https://blog.csdn.net/weixin_43613297/article/details/103939647

java.nio异步线程安全的IO

主宰稳场 提交于 2020-02-04 23:51:11
BIO 方式使得整个处理过程和连接是绑定的,只要连接建立,无论客户端是否有消息发送,都要进行等待处理,一定程度上浪费了服务器端的硬件资源,因此就有了 NIO 方式。Java 对于 NIO 方式的支持是通过 Channel和 Selector 方式来实现,采用的方法为向 Channel注册感兴趣的事件,然后通过 Selector 来获取到发生了事件的 key,如发生了相应的事件,则进行相应的处理,否则则不做任何处理,是典型的Reactor 模式,按照这样的方式,就不用像 BIO 方式一样,即使在没有消息的情况下也需要占据一个线程来阻塞读取消息,从而提升服务器的使用效率, 为实现 TCP/IP+NIO 方式的系统间通讯, Java 提供了 SocketChannel和 ServerSocketChannel两个关键的类,网络 IO 的操作则改为通过ByteBuffer 来实现,具体的基于 java实现TCP/IP+NIO 方式的通讯的方法如下所示。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

HashMap与HashTable的区别

a 夏天 提交于 2020-02-04 07:58:44
(仅列出重要的) 1,Hashtable既不支持Null key也不支持Null value;   HashMap中,null可以作为键,这样的键只有一个,可以有一个或多个键所对应的值为null。 2,Hashtable是线程安全的,它的每个方法中都加入了Synchronize方法。在多线程并发的环境下,可以直接使用Hashtable,不需要自己为它的方法实现同步   HashMap不是线程安全的,在多线程并发的环境下,可能会产生死锁等问题。   虽然HashMap不是线程安全的,但是它的效率会比Hashtable要好很多。这样设计是合理的。在我们的日常使用当中,大部分时间是单线程操作的。HashMap把这部分操作解放出来了。当需要多线程操作的时候可以使用线程安全的ConcurrentHashMap。       ConcurrentHashMap虽然也是线程安全的,但是它的效率比Hashtable要高好多倍。因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。 3,Hashtable默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。   创建时,如果给定了容量初始值,那么Hashtable会直接使用你给定的大小,而HashMap会将其扩充为2的幂次方大小

java并发之hashmap

假装没事ソ 提交于 2020-02-04 07:30:01
在Java开发中经常会使用到hashmap,对于hashmap又了解多少,经常听到的一句话是hashmap是线程不安全的,那为什么是线程不安全的,如何才能保证线程安全,JDK又给我们提供了那些线程安全的类,这些问题是今天讨论的问题, 一、hashmap为什么线程不安全 说到hashmap为什么线程不安全,首先要理解线程安全的定义。简单来讲,指的就是两个以上的线程操作同一个hashmap对象,不会发生资源争抢,hashmap中的数据不会错乱。根据以上的说法,我们大体上看下hashmap的源码,分析下其常用方法put、get的源码。 1、hashmap定义(基于JDK1.8) 经常使用hashmap的方式如下, HashMap map1=new HashMap(); 使用最简单粗暴的方式创建一个HashMap的对象,那么在底层是如何创建的,查看源码如下, /** * Constructs an empty <tt>HashMap</tt> with the default initial capacity * (16) and the default load factor (0.75). */ public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted 根据上面的提示

谈谈线程安全与锁优化

佐手、 提交于 2020-02-04 02:46:02
写在前面 本文是作为阅读《深入理解Java虚拟机》第13章线程安全与锁优化的读书笔记; 线程安全是以多个线程之间存在共享对象为前提的。它并不是一个非黑即白的问题。Brian Goetz 曾就线程安全的“安全程度” 按以下由强至弱做了划分: 不可变;这类对象不需要进行任何线程安全的保障措施,只要这个对象被构建出来,其外部的可见状态永远也不会改变。如果共享数据是一个基本数据类型,那么只要在定义时使用 final 关键字修饰它,就可以保证它是不可变的。如果共享数据是一个对象类型,那就需要保证对象的行为不会对其状态产生任何影响才行,像 String 类的对象。 绝对线程安全;这类的划分的定义和不可变很像,但不可变更加的纯粹,简单。如果一个对象要是绝对线程安全的,那么需要保证多个线程中,对该对象的各种行为调用组合,都会得到想要的结果。举个例子来说, Vector 是线程安全的,但并不是绝对线程安全,比如,在一个线程对一定容量大小的 Vector 进行 remove 操作,另一线程进行 get 操作,最终,你会得到一个数组越界异常,这并不是我们想要的结果。其实,绝对线程安全是一种很苛刻的条件,所以,Java 中所讲的线程安全,通常指的是下面的相对线程安全。 相对线程安全;针对单个对象的单独操作是线程安全的。像上面 Vector 的 get 、remove 等操作。 线程兼容

单例模式——我只有一个对象

与世无争的帅哥 提交于 2020-02-03 22:02:18
面试官:带笔了吧,那写两种单例模式的实现方法吧 沙沙沙刷刷刷~~~ 写好了 面试官:你这个是怎么保证线程安全的,那你知道,volatile 关键字? 类加载器?锁机制???? 点赞+收藏 就学会系列,文章收录在 GitHub JavaEgg ,N线互联网开发必备技能兵器谱 单例模式——独一无二的对象 单例模式,从我看 《Java 10分钟入门》那天就听过的一个设计模式,还被面试过好几次的设计模式问题,今天一网打尽~~ 有一些对象我们确实只需要一个,比如,线程池、数据库连接、缓存、日志对象等,如果有多个的话,会造成程序的行为异常,资源使用过量或者不一致的问题。你也许会说,这种我用全局变量不也能实现吗,还整个单例模式,好像你很流弊的样子,如果将对象赋值给一个全局变量,那程序启动就会创建好对象,万一这个对象很耗资源,我们还可能在某些时候用不到,这就造成了资源的浪费,不合理,所以就有了单例模式。 单例模式的定义 单例模式确保一个类只有一个实例,并提供一个全局唯一访问点 单例模式的类图 单例模式的实现 饿汉式 static 变量在类装载的时候进行初始化 多个实例的 static 变量会共享同一块内存区域 用这两个知识点写出的单例类就是饿汉式了,初始化类的时候就创建,饥不择食,饿汉 public class Singleton { //构造私有化,防止直接new private

线程安全集合

北城余情 提交于 2020-02-01 14:32:08
>>返回《C# 并发编程》 1. 简介 2. 不可变栈和队列 3. 不可变列表 4. 不可变Set集合 5. 不可变字典 6. 线程安全字典 7. 阻塞队列 8. 阻塞栈和包 9. 异步队列 10. 异步栈和包 11. 阻塞/异步队列 1. 简介 不可变集合 不可变集合之间通常 共享 了大部分存储空间,因此其实浪费并不大 因为是无法修改的,所以是 线程安全 的 线程安全集合 可同时被多个线程修改的可变集合 线程安全集合 混合使用了 细粒度锁定 和 无锁 技术,以确保线程被阻塞的时间最短 通常情况下是根本不阻塞 对很多线程安全集合进行 枚举操作 时,内部创建了该集合的一个 快照 (snapshot),并对这个快照进行枚举操作。 线程安全集合的主要 优点 是多个线程可以安全地对其进行访问,而代码只会被阻塞 很短 的时间,或根本 不 阻塞。 下面对常用的属于 不可变集合 和 线程安全集合 类型的,特定数据结构的集合进行说明。 2. 不可变栈和队列 不可变集合 采用的模式是 返回 一个修改过的集合,原始的集合引用是不变化的。 这意味着,如果引用了特定的不可变集合的实例,它是不会变化的。 var stack = ImmutableStack<int>.Empty; stack = stack.Push(13); var biggerStack = stack.Push(7); // 先显示