线程安全

Java并发编程(三)概念介绍

狂风中的少年 提交于 2020-02-23 16:28:26
在构建稳健的并发程序时,必须正确使用线程和锁。但是这终归只是一些机制。要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对 共享的(Shared) 和 可变的(Mutable) 状态的访问。 对象的状态是指存储在 状态 变量(例如实例或静态域)中的数据。 对象的状态可能包括其他 依赖对象的域 。比如某个HashMap的状态不仅是HashMap对象本身,还存储在许多Map.Entry对象中。 "共享"意味着变量可以由多个线程同时访问,而"可变"则意味着变量的值在其生命周期内可以变化。 线程安全性在于如何防止数据上发生 不可控的并发访问 。 一个对象是否 需要是线程安全的 ,取决于它是否被多个线程访问。 要使对象是线程安全的,需要采用 同步机制 来协同对对象可变状态的访问。如果无法实现协同,那么可能导致数据破坏以及其他不该出现的结果。 协同多个线程对变量访问的同步机制主要有: 1. 关键字 synchronized 2. 关键字 volatile 3. 显式锁 (Explicit Lock) 4. 原子变量 协同多线程访问一个可变的状态变量的方法有: 1. 不在线程之间共享该状态变量 2. 将状态变量修改为不可变的变量 3. 在访问状态变量时使用同步 什么是线程安全? 一个类在多线程环境下被访问,这个类始终能表现出正确的行为,那么就称这个类是线程安全的。

JAVA - 容器详解

爷,独闯天下 提交于 2020-02-23 05:55:52
一、ArrayList 长度 可变数组 ,类似于c++ STL中的vector. 元素以 线性方式连续存储 ,内部允许存放重复元素。 允许对元素进行随机的快速访问,但是向ArrayList中 插入和删除元素的速度较慢 。 ArrayList是 非线程安全 的,若要成为线程安全,可以使用:List list=Collections.synchronizedList(new ArrayList()); 数组进行扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量的增长大约是其原容量的1.5倍。 这种操作的代价是很高的,因此在实际使用时,我们 应该尽量避免数组容量的扩张 。 当我们可预知要保存的元素的多少时,要在构造ArrayList实例时,就指定其容量,以避免数组扩容的发生。 二、LinkedList 内部采用 双向循环链表 实现,类似于c++ STL中的list. 插入和删除元素的速度较快 ,随机访问的速度较慢. LinkedList单独具有addFirst(),addLast(),getFirst(),getLast(),removeFirst()和removeLast()方法. 这些方法使得它 可以作为堆栈、队列和双向队列来 使用. LinkedList也是 非线程安全 的. 三、HashMap 基于哈希表的Map接口实现,类似于c++ STL中的unordered

设计模式_单例模式

微笑、不失礼 提交于 2020-02-22 11:00:56
单例模式概述 1、核心: 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。 2、单例模式的优点: 1)由于单例模式只生成一个实例对象,减少了系统的性能开销。当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决 2)单例模式可以在系统设置全局的访问点,优化共享资源的访问,例如可以设计一个单例类,负责所有数据表的映射处理 常见的五种单例模式实现方式: 1、饿汉式(线程安全,调用效率高。但是,不能延时加载。) /* * 测试单例模式 * * 饿汉模式 */ public class SingletonDemo1 { //类初始化时立即加载对象(没有延迟加载的优势),天然的线程安全 private static SingletonDemo1 instance = new SingletonDemo1 ( ) ; //构造器私有化 private SingletonDemo1 ( ) { } //方法没有同步,调用效率高 public static SingletonDemo1 getInstance ( ) { return instance ; } } 2、懒汉式(线程安全,调用效率不高。但是,可以延时加载。) /* * 测试单例模式 * * 懒汉模式 */ public class

安全并发之先行发生原则

蓝咒 提交于 2020-02-21 03:47:32
java天生就是多线程的语言,线程安全则是一个必须的要求。 给你一段代码,你如何判定其是否是线程安全的?那么,自然就要有一套绝对的理论给你的证明提供依据了。   先行发生原则,可以帮你判定是否并发安全的,从而不必去猜测是否是线程安全了!   如果Java内存模型中所有有序性都靠volatile和synchronized来完成,那么编写代码会很繁琐,但日常Java开发中并没有感受到这一点,正是因为Java语言的“先行发生”原则。这个原则非常重要,它是判断数据是否存在竞争、线程是否安全的主要依据。   先行发生是Java内存模型中定义的两项操作数之间的偏序关系,如果说操作A先行发生于操作B,就是说在发生操作B之前,操作A产生的影响能被操作B观察到,“影响”包括修改了内存中共享变量的值、发送了消息、调用了方法等。   下面是Java内存模型中一些“天然的”先行发生关系,这些先行发生关系无需任何同步协助器协作即可存在,可以直接在编码中使用。如果两个关系不在此列,而又无法通过这些关系推导出来,它们的顺序就无法保证,虚拟机可以对它们任意重排序。    程序次序规则: 同一个线程内,按照代码出现的顺序,前面的代码 happens-before 后面的代码,准确的说是控制流顺序,因为要考虑到分支和循环结构。    管程锁定规则: 对于一个监视器锁的unLock操作 happens-before

Java集合--线程安全(CopyOnWrite机制)

老子叫甜甜 提交于 2020-02-19 12:23:06
5 Java并发集合 5.1 引言 在前几章中,我们介绍了Java集合的内容,具体包括ArrayList、HashSet、HashMap、ArrayQueue等实现类。 不知道各位有没有发现,上述集合都有一个共同的特点,那就是线程不安全性,在并发情况下都不能保证数据的一致性。(当然,这个集合必须是共享了,所以才会有数据不一致) 所以,当我们在进行并发任务时候,共享了一个不适用于并发的数据结构,也就是将此数据结构变成了程序中的成员变量,那么我们将会遇到数据的不一致,进而影响到我们程序的运行。 为了应对并发场景的出现,Java在后续迭代过程中(具体应该是JDK1.5版本),推出了java.util.concurrent包。该包的出现,让Java并发编程变得更加轻松,帮助开发者编写更加高效、易维护、结构清晰的程序。 在java.util.concurrent包中,不但包含了我们本篇要说的线程安全的集合,还涉及到了多线程、CAS、线程锁等相关内容,可以说是完整覆盖了Java并发的知识栈。 对于Java开发人员来说,学好java.util.concurrent包下的内容,是一个必备的功课,也是逐渐提升自己的一个重要阶段。 5.2 并发集合实现1 JDK1.5的出现,对于集合并发编程来说,java developer有了更多的选择。不过,在JDK1.5之前,Java也还是提供了一些解决方案。

1-6并发编程(6)

六眼飞鱼酱① 提交于 2020-02-19 07:21:14
文章目录 1写一个线程安全的单例模式 2 有N张火车票,每张票都有一个编号,同时有10个窗口对外售票,请写一个模拟程序 2.1 第一个程序 2.2第二个程序:使用Vector 2.3第三个程序:使用Vector,在加一个锁 2.4第四个程序:并发容器 ConcurrentQueue 1写一个线程安全的单例模式 /** * 线程安全的单例模式: * * 阅读文章:http://www.cnblogs.com/xudong-bupt/p/3433643.html * * 更好的是采用下面的方式,既不用加锁,也能实现懒加载 * * @author 马士兵 */ package yxxy . c_023 ; import java . util . Arrays ; public class Singleton { private Singleton ( ) { System . out . println ( "single" ) ; } private static class Inner { private static Singleton s = new Singleton ( ) ; } public static Singleton getSingle ( ) { return Inner . s ; } public static void main ( String [ ]

并发编程初探-线程安全性

依然范特西╮ 提交于 2020-02-19 04:12:35
  在Java并发编程中,对于线程安全是非常重要的,也是必须要考虑的一个问题.可以这么说,只要涉及到网络的,都必须考虑线程安全问题.好了,开始噼里啪啦地开始敲代码之前,我觉得有必要了解一些文绉绉的理论知识,因为这些理论知识是我们敲出来的代码是否是线程安全的一个依据.     当多个线程访问某个状态变量并且其中有一个线程执行写入操作的时候,必须考虑采用同步机制来协同这些线程对变量的访问,Java中的主要同步机制是关键字synchronized,它提供了一种独占的加锁方式,但"同步"这个术语还包括类型的变量,显式锁(Explicit)以及原子变量.   如果当多个线程访问同一个可变状态变量时,没有使用合适的同步,那么就会出现错误.有三种方式可以修复这个问题:   1)不在线程间共享该状态变量   2)将状态变量修改为不可变的变量   3)在访问状态变量时使用同步   当设计线程安全的类时,良好的面向对象技术,不可修改性,以及明晰的不变性规范都能起到一定的帮助作用.   当多个线程访问某个类时,不管运行时环境采用何种调用方式,或者这些线程将如何交替执行,并且在主调代码中不需要任务额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的.   这里的正确性是指某个类的行为与其规范安全一致,也就是说这个类是实现什么功能的就正确的实现了什么功能.   在线程安全的类中

201521123044 《Java程序设计》第11周学习总结

狂风中的少年 提交于 2020-02-17 19:15:54
1. 本章学习总结 2. 书面作业 本次PTA作业题集 多线程 1.互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) 1.1 除了使用synchronized修饰方法实现互斥同步访问,还有什么办法实现互斥同步访问(请出现相关代码)? 题集4-4和4-5使用到的Lock对象和Condition对象实现互斥同步访问 //关键代码: public void deposit(int money) {// synchronized lock.lock(); try { balance += money; plus.signalAll(); } finally { lock.unlock(); } } public void withdraw(int money){ lock.lock(); try{ try{ while(this.getBalance()<=0) condition.await(); condition.signal(); }catch(Exception e){ System.out.println(e); } this.balance=this.getBalance()-money; if(balance<0) throw new IllegalStateException(balance+""); }finally{ lock.unlock(); }

python-多线程(原理篇)

核能气质少年 提交于 2020-02-17 15:37:07
/*--> */ /*--> */ 多线程的基本概念 语言学习总是绕不过一些东西,例如多进程和多线程,最近越来越发现,上来看几个实例练习一下过几天就不知其所以然了。所以还是先看看原理,在看实例练习吧! 线程的概念 概念:线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。其实平时我们启动程序,其实是启动的进程,但是在往下细分的话,其实是进程的一个或者多个线程完成的功能。 好处 :(1)易于调度。 (2)提高并发性。通过线程可方便有效地实现并发性。进程可创建多个线程来执行同一程序的不同部分。 (3)开销少。创建线程比创建进程要快,所需开销很少。 (4)利于充分发挥多处理器的功能。通过创建多线程进程,每个线程在一个处理器上运行,从而实现应用程序的并发性,使每个处理器都得到充分运行。 多线程vs多进程 操作系统会为每个进程分配不同的内存块,而多个线程共享进程的内存块。这带来最直接的不同就是创建线程的开销远小于创建进程的开销。 同时,由于内存块不同,所以进程之间的通信相对困难。而线程间的通信简单快速,就是共享进程内的全局变量。 但是,进程的调度由操作系统负责

如何线程安全的使用HashMap

雨燕双飞 提交于 2020-02-17 14:20:13
HashMap: 线程不安全,链表结构,效率高; Hashtable : 线程安全,但效率低,因为是Hashtable是使用synchronized的,所有线程竞争同一把锁; Synchronized Map: 线程安全,但效率低,一次性锁住整张表来保证线程安全,所以每次只能有一个线程来访问map。 ConcurrentHashMap:线程安全而且效率高,因为它包含一个segment数组,将数据分段存储,给每一段数据配一把锁。           在理想状态下,ConcurrentHashMap 可支持16个线程执行并发写操作,及任意数量线程的读操作。 如何线程安全的使用HashMap : 以下三种方式: Hashtable ConcurrentHashMap Synchronized Map    来源: https://www.cnblogs.com/lgg20/p/12321427.html