synchronized

Lock与synchronized 的区别

不想你离开。 提交于 2020-01-25 07:13:37
多次思考过这个问题,都没有形成理论,今天有时间了,我把他总结出来,希望对大家有所帮助 1、 ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候 线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定, 如果使用 synchronized ,如果A不释放,B将一直等下去,不能被中断 如果 使用ReentrantLock,如果A不释放,可以使B在等待了足够长的时间以后,中断等待,而干别的事情 ReentrantLock获取锁定与三种方式: a) lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁 b) tryLock(), 如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false; c)tryLock(long timeout, TimeUnit unit), 如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false; d) lockInterruptibly:如果获取了锁定立即返回,如果没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断 2、 synchronized是在JVM层面上实现的

Java 多线程(七) 线程间的通信

坚强是说给别人听的谎言 提交于 2020-01-25 00:22:41
Java 多线程(七) 线程间的通信——wait及notify方法 线程间的相互作用   线程间的相互作用: 线程之间需要一些协调通信,来共同完成一件任务。   Object类中相关的方法有两个notify方法和三个wait方法:    http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html   因为wait和notify方法定义在Object类中,因此会被所有的类所继承。   这些方法都是 final 的,即它们都是不能被重写的,不能通过子类覆写去改变它们的行为。 wait()方法    wait()方法使得当前线程必须要等待,等到另外一个线程调用notify()或者notifyAll()方法。    当前的线程必须拥有当前对象的monitor,也即lock,就是锁。   线程调用wait()方法,释放它对锁的拥有权,然后等待另外的线程来通知它(通知的方式是notify()或者notifyAll()方法),这样它才能重新获得锁的拥有权和恢复执行。   要确保调用wait()方法的时候拥有锁,即,wait()方法的调用必须放在synchronized方法或synchronized块中。    一个小比较:   当线程调用了wait()方法时,它会释放掉对象的锁。   另一个会导致线程暂停的方法:Thread

java - synchronized与lock的区别

烈酒焚心 提交于 2020-01-24 23:41:24
synchronized与lock的区别 原始构成 synchronized是关键字属于JVM层面   monitorenter(底层是通过monitor对象来完成,其实wait/notify等对象也依赖于monitor独享只有在同步块或方法中才能调wait/notify等方法)   monitorexit Lock是具体类(java.utl.concurrent.locks.Lock)是api层面的锁 使用方法 synchronized不需要用户去手动释放锁,当synchronized代码执行完后系统会自动让线程释放对锁的占用 ReentrantLock则需要用户去手动释放锁若没有主动释放锁,就有可能导致出现死锁现象, 需要lock()和unlock()方法配合try/final语句块来完成。 等待是否可中断 synchronized不可中断,除非抛出异常或者正常运行完成 ReentrantLock可中断 设置超时方法tryLock(long timeout,TimeUnit unit)、lockInteerruptibly()放代码块中,调用interrupt()方法可中断 加锁是否公平 synchronized非公平锁 ReentrantLock两者都可以,默认公平锁,构造方法可以传入boolean值,true为公平锁,false为非公平锁。

java - 锁的种类及详解

醉酒当歌 提交于 2020-01-24 16:43:49
锁类型 锁根据其特性能够划分出各种各样的锁类型,该文主要介绍以下锁的作用及特性 乐观锁/悲观锁 独享锁/共享锁 互斥锁/读写锁 可重入锁 公平锁/非公平锁 分段锁 偏向锁/轻量级锁/重量级锁 自旋锁 乐观锁/悲观锁 乐观锁与悲观锁并不是特指某两种类型的锁,是人们定义出来的概念或思想,主要是指看待并发同步的角度。 乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS(Compare and Swap 比较并交换,属于计算机底层的CPU原子操作)实现的。 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。比如Java里面的同步原语synchronized关键字的实现就是悲观锁。 悲观锁适合写操作非常多的场景,乐观锁适合读操作非常多的场景,不加锁会带来大量的性能提升。 乐观锁在Java中的使用,是无锁编程,常常采用的是CAS算法,典型的例子就是java.util.concurrent.atomic包下的原子类

synchronized和volatile的区别

夙愿已清 提交于 2020-01-24 15:24:37
Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存重新读取该成员的值,而且,当成员变量值发生变化时,强迫将变化的值重新写入共享内存,这样两个不同的线程在访问同一个共享变量的值时,始终看到的是同一个值。 java语言规范指出:为了获取最佳的运行速度,允许线程保留共享变量的副本,当这个线程进入或者离开同步代码块时,才与共享成员变量进行比对,如果有变化再更新共享成员变量。这样当多个线程同时访问一个共享变量时,可能会存在值不同步的现象。 而volatile这个值的作用就是告诉VM:对于这个成员变量不能保存它的副本,要直接与共享成员变量交互。 建议:当多个线程同时访问一个共享变量时,可以使用volatile,而当访问的变量已在synchronized代码块中时,不必使用。 缺点:使用volatile将使得VM优化失去作用,导致效率较低,所以要在必要的时候使用。 来源: https://www.cnblogs.com/zhengtu2015/p/4871460.html

理解什么是线程安全性、原子性

只愿长相守 提交于 2020-01-24 08:47:08
目录 •写在前面 •原子性 加锁机制 •写在前面 进程想要执行任务需要依赖线程,换句话说就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程。提到多线程这里要说两个概念,就是串行和并行,搞清楚这个我们才能更好的理解多线程。所谓串行其实是相对于单条线程来执行多个任务来说的,我们就拿下载文件来举个例子,我们下载多个文件,在串行中它是按照一定的顺序去进行下载的,也就是说必须等下载完A之后,才能开始下载B,它们在时间上是不可能发生重叠的。 要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享的和可变的状态的访问。要是的对象是线程安全的,需要采用同步机制来协同对对象可变状态的访问,如果无法实现协同,那么可能会导致数据破坏以及其他不该出现的结果。java中的同步机制是关键字synchronized,它提供了独占式的加锁方式,不仅如此还包括volatile类型变量,显式锁Lock以及原子变量。 单线程近似定义为“所见即所知”,那么定义线程安全性,则当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类是线程安全的。一个类在单线程中运行都不正确,那么它肯定是不会是线程安全的。如果正确的实现了某个对象,那么在任何操作中(包括调用对象的公有方法或者对其公有域进行读写操作)都不会违背不变性条件或后验条件

Android源码分析之SharedPreferences

谁说我不能喝 提交于 2020-01-24 02:38:07
  在Android的日常开发中,相信大家都用过SharedPreferences来保存用户的某些settings值。Shared Preferences 以键值对的形式存储私有的原生类型数据,这里的私有的是指只对你自己的app可见的,也就是说别的app是无法访问到的。 客户端代码为了使用它有2种方式,一种是通过Context#getSharedPreferences(String prefName, int mode)方法, 另一种是Activity自己的getPreferences(int mode)方法,其内部还是调用了前者只是用activity的类名做了prefName而已, 我们先来看下Conext#getSharedPreferences的内部实现。其具体实现在ContextImpl.java文件中,代码如下: @Override public SharedPreferences getSharedPreferences(String name, int mode) { SharedPreferencesImpl sp; // 这个是我们接下来要分析的重点类 synchronized (ContextImpl.class) { if (sSharedPrefs == null) { // sSharedPrefs是一个静态的ArrayMap,注意这个类型

volatile和synchronized的区别

好久不见. 提交于 2020-01-23 20:10:40
volatile和synchronized的区别 volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。 volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。 volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。 volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。 有可能有些读者还是会不大理解这里的区别,那我现在再来讲一讲线程安全的两个方面: 执行控制 和 内存可见 。 执行控制的目的是控制代码执行顺序及是否可以并发执行。 内存可见控制的是线程执行结果在内存中对其它线程的可见性。(根据Java内存模型的实现,线程在具体执行时,会先拷贝主存数据到线程本地(CPU缓存),操作完成后再把结果从线程本地刷到主存。) synchronized关键字解决的就是执行控制,它能控制代码执行的顺序,即如果一个线程正在进行被synchronized修饰的代码块时,它会阻止其他的线程进行这段代码块。更重要的是,synchronized还会创建一个内存屏障,内存屏障指令保证了所有CPU操作结果都会直接刷到主存中

线程的Synchronized锁

眉间皱痕 提交于 2020-01-23 15:44:30
1. 多线程可能出现的安全问题 public class Synchronizedtest implements Runnable { int i = 10; //共享变量 @Override public void run() { if( i == 10 ){ System.out.println("i == 10"); sys i++; } } public static void main(String[] args) throws InterruptedException { Synchronizedtest st = new Synchronizedtest(); Thread t1 = new Thread(st,"线程1"); Thread t2 = new Thread(st,"线程2"); t1.start(); // t1.sleep(1000); 第一次测试先注释掉,第二次测试打开,下面为两次测试结果 t2.start(); } } i == 10 i == 10 i == 10 问题分析: i++ 这个操作是非原子性的,分为三步: 读取 i 的值 将读取的数值 +1 将数值写回 i 线程t1,读取了i 值为10,在把值写回 i (i++ = 11) 之前,线程t2就读取了 i 的值,此时t1并未修改 i 的值,所以 i 还是等于10 因此二者判断 i

Java面试题-并发篇十六

孤者浪人 提交于 2020-01-23 03:39:17
161,Java内存模型是什么? Java内存模型规定和指引Java程序在不同的内存架构、CPU和操作系统间有确定性地行为。它在多线程的情况下尤其重要。Java内存模型对一个线程所做的变动能被其它线程可见提供了保证,它们之间是先行发生关系。这个关系定义了一些规则让程序员在并发编程时思路更清晰。比如,先行发生关系确保了: 线程内的代码能够按先后顺序执行,这被称为程序次序规则。 对于同一个锁,一个解锁操作一定要发生在时间上后发生的另一个锁定操作之前,也叫做管程锁定规则。 前一个对volatile的写操作在后一个volatile的读操作之前,也叫volatile变量规则。 一个线程内的任何操作必需在这个线程的start()调用之后,也叫作线程启动规则。 一个线程的所有操作都会在线程终止之前,线程终止规则。 一个对象的终结操作必需在这个对象构造完成之后,也叫对象终结规则。 可传递性 更多介绍可以移步并发编程网: (深入理解java内存模型系列文章:http://ifeve.com/java-memory-model-0) 162,Java中interrupted 和isInterruptedd方法的区别? interrupted() 和 isInterrupted()的主要区别是前者会将中断状态清除而后者不会。Java多线程的中断机制是用内部标识来实现的,调用Thread