线程安全

List集合

五迷三道 提交于 2020-01-13 09:37:33
List集合有序、元素可重复。以元素的添加顺序作为集合的排列顺序,用下标索引集合中的元素。 List因为使用下标索引元素,所以元素可重复。Set使用元素本身来索引,所以元素不能重复。 List的继承关系: List继承了Collection的所有方法,也有自身的一些方法(下标操作): void add(int index,Object element) 在指定处插入一个元素 boolean addAll(int index,Collection c) 在指定处插入c的所有元素 Object get(int index) 获取指定位置处的元素 int indexOf(Object obj) 返回该对象在集合中第一次出现的位置 int lastIndexOf(Object obj) 最后一次出现的位置 Object remove(int index) 删除并返回指定位置的元素 Object set(int index,Object obj) 替换/设置指定位置的元素,并返回旧的元素 List subList(int start,int end) 返回子List ListIterator listIterator() 返回List集合专用的迭代器 Java8新增了sort()、replaceAll()2个方法,可以自定义排序规则、匹配模板。 List接口常用的实现类: 1

Java_多线程实现同步

二次信任 提交于 2020-01-13 01:56:47
多线程之间实现同步 理解线程安全 synchronized用法 死锁 Java内存模型 Vlolatile 关键字 ThreadLock 关键字 理解线程安全 什么是线程安全? 当多个线程同时对共享的同一个 全局变量或静态变量 做写的操作时 ,可能会发生数据冲突问题,也就是线程安全问题。 但是 做读操作是不会发生数据冲突问题 。 线程安全解决办法 : 使用多线程之间同步synchronized或使用锁(lock)。 原理: 同一时间内,只让当前一个线程进行对数据进行执行操作。当当前线程执行完成后释放锁,才能让其他线程进行操作执行。避免了同时对数据的操作,这样的话就可以解决线程的不安全问题,也就实现了数据的同步。 synchronized用法: synchronized有两种用法: 第一种:将可能会发生线程安全问题的代码,给包括起来,称为同步代码块。 代码如下: synchronized(锁){   //可能会发生线程冲突问题的代码块 } 第二种: 在方法上修饰synchronized,称为同步函数。 代码如下: public synchronized void 方法名() {   //可能会发生线程冲突问题的代码块 } 若在方法上加上 static 静态关键字则成为静态同步函数; 静态同步函数使用的锁是该函数所属字节码文件对象; 可以使用 getClass() 的方法获取

netty对于channel的线程安全保证

帅比萌擦擦* 提交于 2020-01-13 01:08:23
netty的几个重要特性 1.一个EventLoopGroup当中包含一个或多个EventLoop 2.一个EventLoop在其生命周期内只和唯一的一个Thread线程绑定(即一个io线程) 3.所有由EventLoop处理的各种io事件都将在其所关联的io线程上执行,因为是单线程保证了线程安全 4.一个Channel在其生命周期内只会注册在一个EventLoop(selector)上 5.运行期间,一个EventLoop会被分配给一个或多个channel 重点来看第三点netty是如何实现的呢? 其中eventLoop.inEventLoop()方法的逻辑是: 判断当前线程是否是EventLoop中所绑定的那个唯一的io线程 如果是,则直接执行相应的channelHandler,处理该io事件 若不是,则将需要执行的channelHandler封装成一个任务交给EventLoop中io线程去执行,EventLoop中具体保存任务的是一个FIFO队列,而且又是单线程执行,所以在保证线程安全的同时也保证了任务的有序性。 (这里同时要注意的是,在channelHandler中要避免执行耗时或阻塞的处理逻辑,这样会导致后续channelHandler或其他绑定在该EventLoop上的channel的事件响应阻塞,从而影响性能。解决方式

Linux线程(三)

假装没事ソ 提交于 2020-01-11 23:48:26
Linux线程(三) 一、互斥量 根据前面的分析,得到的结果不是我们想要的原因是–ticket操作不是原子操作,这个共享资源可能并发的切换大其他线程,导致有多个线程同时影响到这个共享资源,所以导致得到的结果不对。 1.解决方法(加锁—>Linux中叫这把锁为互斥量): 代码必须有互斥行为:当有一个执行流(有一个线程)进入临界区时,不允许其他线程进入该临界区 如果多个线程同时要求执行临界区的代码,并且临界区内没有线程在执行,那么只允许一个线程进入该临界区 如果线程不在临界区内执行,那么该线程不能阻止其他线程进入临界区 二、.互斥量的接口: 1.初始化互斥量 方法一:静态分配 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER 方法二:动态分配 int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); 功能:初始化互斥量 参数:pthread_mutex_t *restrict mutex:要初始化的互斥量 const pthread_mutexattr_t *restrict attr:指定了新建互斥锁的属性。如果参数attr为NULL,则使用默认的互斥锁属性,默认属性为快速互斥锁 返回值

9. 线程安全

偶尔善良 提交于 2020-01-11 06:23:26
当多个线程访问一个对象时,若不用考虑这些线程在运行时环境下的调度和交替执行,也不需要额外的同步,或者在调用方法进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的。-----摘自《Java Concurrency in Practice》 一、Java中的线程安全 Java中各种操作共享数据可以分为以下几种: 不可变 绝对线程安全 相对线程安全 线程兼容 线程对立 1. 不可变 在Java中不可变得对象一定是线程安全的,无论是对象的方法实现还是方法的调用者,都不需要再采取任何的线程安全保障措施。若共享数据是一个基本数据类型,只要在定义事使用 final 关键字来修饰就它可以保证它是不可变的。若共享数据是一个引用对象,则还需要保证对象的行为不会对其状态产生任何影响才行。 保证对象行为不影响自己状态最简单的就是将对象中带有状态的变量都声明为 final。 2. 绝对线程安全 绝对安全完全满足最上面给出的定义。在Java API中标注自己是现成安全的类,大多数都不是绝对线程安全的。必须要进行相应的同步处理。 3. 相对线程安全 相对线程安全是我们通常意义上讲的线程安全。它需要保证对这个对象单独的操作是线程安全的,我们在调用时不需要做额外的保障措施,但是对于一些特定顺序的连续调用,就可能需要在调用端使用额外的同步手段来保证调用的正确性。在Java中

JVM线程安全

吃可爱长大的小学妹 提交于 2020-01-11 05:12:35
线程安全的安全程度由强至若可划分为:不可变(final),绝对线程安全(不需要任何措施保证程序运行的正确性),相对线程安全(单独调用线程安全,连续调用非线程安全,需要额外的同步措施),线程兼容(通过的同步措施保证程序正确性),线程对立。 JAVA虚拟机中线程安全的实现方式主要有两种 1.阻塞同步 2.非阻塞同步 一、两种同步方案 1.阻塞同步通过获取对象锁的方式来保证线程安全,synchronized关键字经过编译后产生两条字节码monitorenter,monitorexit,进入代码块时获取对象锁,synchronized具有可重入性,monitorenter计数+1,monitorexit计数-1,计数等于0释放锁,获得锁失败的线程进入阻塞状态,JAVA的线程需要在用户态和内核态相互转换,因此synchronized是重量级。 2.非阻塞同步的实现得益于计算机的CAS操作(原子操作),比较和交换,工作内存中存储一个变量副本,当需要对主存中的变量进行操作的时候将变量副本和实际值进行比较,若相等才能将预期值写到主寸中,这一个过程是一个原子操作,虽然这样省去了线程状态的转换带来的消耗,但由于只关心值是否相等,所以这样的同步方案就会有ABA的问题。 二、锁优化 为了减少线程在用户态和内存态之间的转换带来的消耗,在JDK1.6的版本中对于锁优化做了许多工作。 1.自旋锁 简单的说

java多线程之--(2)实现线程安全的三种方式

|▌冷眼眸甩不掉的悲伤 提交于 2020-01-10 16:38:06
我们在开发中直接使用线程是无法保证线程安全的,有可能出现多个线程先后更改数据造成所得到的数据是脏数据,那么怎么解决这种问题呢,就要应用到线程安全的三种解决方法了 1. 线程安全 线程安全: 如果有多个线程在同时运行,而这些线程可能会同时运行某段代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的 线程不安全: 当有多个线程在同时运行,这些线程同时运行一段代码(同一段任务代码,同一个run方法),操作同一个共享数据时, 这时候可能就会出现线程的安全问题,即线程不安全的.,有可能出现多个线程先后更改数据造成所得到的数据是脏数据 1.举例说明线程不安全 模拟多个窗口共同卖100张票, 需要窗口,采用线程对象来模拟;需要票,Runnable接口子类来模拟 模拟票 创建 Ticket 任务类 /** * @Description * @auther 宁宁小可爱 * @create 2020-01-10 14:29 */ public class Ticket implements Runnable { // 总共一百张票 private int ticket = 100 ; /* * 执行卖票操作 * */ @Override public void run ( ) { // 窗口永远卖票 while ( true ) { if (

java web 学习五(servlet开发1)

。_饼干妹妹 提交于 2020-01-10 07:05:27
一、Servlet简介   Servlet是sun公司提供的一门用于开发动态web资源的技术。   Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:   1、编写一个Java类,实现servlet接口。   2、把开发好的Java类部署到web服务器中。   按照一种约定俗成的称呼习惯,通常我们也把实现了servlet接口的java程序,称之为Servlet 二、Servlet的运行过程 Servlet程序是由WEB服务器调用,web服务器收到客户端的Servlet访问请求后:   ①Web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。   ②装载并创建该Servlet的一个实例对象。   ③调用Servlet实例对象的init()方法。   ④创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。   ⑤WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。 三

一文聊聊ConcurrentHashMap

孤人 提交于 2020-01-10 04:03:15
1.ConcurrentHashmap简介 在使用 HashMap 时在多线程情况下扩容会出现CPU接近100%的情况,因为hashmap并不是线程安全的,通常我们可以使用在java体系中古老的 hashtable 类,该类基本上所有的方法都采用synchronized进行线程安全的控制,可想而知,在高并发的情况下,每次只有一个线程能够获取对象监视器锁,这样的并发性能的确不令人满意。另外一种方式 通过Collections的Map<K,V> synchronizedMap(Map<K,V> m)将hashmap包装成一个线程安全的map 。比如SynchronzedMap的put方法源码为: public V put(K key, V value) { synchronized (mutex) {return m.put(key, value);} } 实际上 SynchronizedMap实现依然是采用synchronized独占式锁进行线程安全的并发控制的 。同样,这种方案的性能也是令人不太满意的。针对这种境况,Doug Lea大师不遗余力的为我们创造了一些线程安全的并发容器,让每一个java开发人员倍感幸福。 相对于hashmap来说,ConcurrentHashMap就是线程安全的map,其中利用了锁分段的思想提高了并发度 。 ConcurrentHashMap在JDK1

Java面试题-集合框架篇三

感情迁移 提交于 2020-01-08 21:45:11
21、ArrayList和Vector的区别 这两个类都实现了List接口(List接口继承了Collection接口),他们都是有序集合,即存储在这两个集合中的元素的位置都是有顺序的,相当于一种动态的数组,我们以后可以按位置索引号取出某个元素,并且其中的数据是允许重复的,这是与HashSet之类的集合的最大不同处,HashSet之类的集合不可以按索引号去检索其中的元素,也不允许有重复的元素。 ArrayList与Vector的区别主要包括两个方面:. (1)同步性: Vector是线程安全的,也就是说是它的方法之间是线程同步的,而ArrayList是线程序不安全的,它的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使用ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用Vector,因为不需要我们自己再去考虑和编写线程安全的代码。 (2)数据增长: ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加ArrayList与Vector的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元,每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。Vector默认增长为原来两倍,而ArrayList的增长策略在文档中没有明确规定