synchronized

java并发基础知识

跟風遠走 提交于 2020-01-28 20:44:52
  这几天全国都是关键时候,放假了,还是要学习啊!很久没有写博客了,最近看了一本书,有关于java并发编程的,书名叫做“java并发编程之美”,讲的很有意思,这里就做一个笔记吧!     有需要openjdk8源码的,可以直接下载 链接:https://pan.baidu.com/s/1_uT99PLxH-STcs0zl0Mhuw 提取码:ov5b 一.了解并发和并行   并发:指的是 同一时间段内 多个任务在执行,并且没有执行结束;就好像你用一个手机看视频,你一下子想看熊出没,一下子又想看喜羊羊,那么你会怎么办?可以这个视频看几秒钟,然后那个视频看几秒钟,最关键的是当你从熊出没->喜羊羊,然后再跳到熊出没的时候,可以直接跳到上次看的记录的位置,这个才是并发最重要的地方;   在这里,你的眼睛就相当于一个cpu,在来回的切换视频,每个视频就是一个线程,然后可以跳转回上次的最后观看的位置,这功能就是类似PC计数器的作用,可以保存每个线程切换时候的上下文;   并行:理解了上面的并发,那么并行就很好理解!记得看过火影没有,可以知道鸣人用影分身修炼的情节,这个就是并行!如果你会影分身,那么你和你的分身分别用一个手机去看熊出没和喜羊羊,然后解除影分身,那么你就一下子同时看完两集了!哈哈哈,这个比喻还行吧!其实就是有两个CPU分别去执行一个线程,再把运行后的结果汇总   在多线程编程实践中

java中常用的锁机制

*爱你&永不变心* 提交于 2020-01-28 20:44:38
基础知识 基础知识之一:锁的类型 锁就那么几个,只是根据特性,分为不同的类型 锁的概念 在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制。锁旨在强制实施互斥排他、并发控制策略。 锁通常需要硬件支持才能有效实施。这种支持通常采取一个或多个原子指令的形式,如"test-and-set", "fetch-and-add" or "compare-and-swap"”。这些指令允许单个进程测试锁是否空闲,如果空闲,则通过单个原子操作获取锁。 锁的三个概念 1、锁开销 lock overhead 锁占用内存空间、 cpu初始化和销毁锁、获取和释放锁的时间。程序使用的锁越多,相应的锁开销越大 2、锁竞争 lock contention 一个进程或线程试图获取另一个进程或线程持有的锁,就会发生锁竞争。锁粒度越小,发生锁竞争的可能性就越小 3、死锁 deadlock 至少两个任务中的每一个都等待另一个任务持有的锁的情况锁粒度是衡量锁保护的数据量大小,通常选择粗粒度的锁(锁的数量少,每个锁保护大量的数据),在当单进程访问受保护的数据时锁开销小,但是当多个进程同时访问时性能很差。因为增大了锁的竞争。相反,使用细粒度的锁(锁数量多,每个锁保护少量的数据)增加了锁的开销但是减少了锁竞争。例如数据库中,锁的粒度有表锁、页锁、行锁、字段锁

volatile关键字

吃可爱长大的小学妹 提交于 2020-01-28 20:42:38
一、简介 volatile是Java提供的一种轻量级的同步机制。Java 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量,相比于synchronized(synchronized通常称为重量级锁),volatile更轻量级,因为它不会引起线程上下文的切换和调度。但是volatile 变量的同步性较差(有时它更简单并且开销更低),而且其使用也更容易出错。 二、并发编程的3个基本概念 (1)原子性 ​ 定义: 即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 ​ 原子性是拒绝多线程操作的,不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作。简而言之,在整个操作过程中不会被线程调度器中断的操作,都可认为是原子性。例如 a=1是原子性操作,但是a++和a +=1就不是原子性操作。Java中的原子性操作包括: ​ a. 基本类型的读取和赋值操作,且赋值必须是数字赋值给变量,变量之间的相互赋值不是原子性操作。 ​ b.所有引用reference的赋值操作 ​ c.java.concurrent.Atomic.* 包中所有类的一切操作 (2)可见性 ​ 定义: 指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。 ​ 在多线程环境下

Lock和synchronized的选择

a 夏天 提交于 2020-01-28 14:12:11
学习资源: http://www.cnblogs.com/dolphin0520/p/3923167.html 一.java.util.concurrent.locks包下常用的类 1.Lock public interface Lock { void lock() ;//用来获取锁。如果锁已被其他线程获取,则进行等待。 void lockInterruptibly () throws InterruptedException;//当通过这个方法去获取锁时,如果线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态。也就使说,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有在等待,那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程。 boolean tryLock ();//是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。 boolean tryLock( long time, TimeUnit unit) throws InterruptedException ;//和tryLock()方法是类似的

设计模式之创建型模式---单例模式

牧云@^-^@ 提交于 2020-01-28 09:46:26
单例模式(Singleton) 单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处: 1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。 2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。 3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。 核心思想:构造函数必须私有制。 使用场景: 1、要求生产唯一序列号。 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。 注意事项:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。 单例模式的六种创建形式: 1、懒汉式,线程不安全 是否 Lazy 初始化:是 是否多线程安全:否 实现难度:易 描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以 严格意义上它并不算单例模式。 这种方式

java并发变成及juc包的应用

╄→尐↘猪︶ㄣ 提交于 2020-01-28 03:51:22
多线程: windows操作系统是多任务操作系统,它以进程为单位,一个进程是一个包含有自身地址的程序,每个正在独立执行的程序都称为进程,进程是系统进行资源分配和调用的独立单位,每个进程有自己的内存空间和系统资源。系统可以分配给每个进程一段有限的使用CPU时间,CPU在这个时间片中执行某个进程,然后下一个时间片又跳到另一个进程中去执行,由于CPU转换较快,所以使的每个进程好像同时进行,多核CPU的多核同时运行,但是进程数远远大于核数,所以还是要依靠切换进程来做。一个线程则是进程中的执行流程,一个进程中可以同时包括多个线程,每个线程也可以得到一小段程序的执行时间,这样一个进程就可以具有多个并发执行的线程,在单线程中,程序的代码按照调用顺序依次往下执行,如果需要一个进程同时完成多段代码的操作,就需要产生多线程(多条执行路径)。多线程可以提高应用程序的使用率,为了有更高的几率抢到CPU的执行权,但我们不能保证哪一个线程能够在哪一个时刻抢到,所以线程的执行有随机性。在并发编程中,我们通常会遇到以下三个问题:原子性问题,可见性问题,有序性问题。 线程的两种调度模型:平均分配每个线程占用CPU的时间片,上面说的就是这种,第二种就是抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,会随机选一个,优先级高仅仅表示线程获取的cpu时间片的几率相对对多些

线程安全与锁优化

你说的曾经没有我的故事 提交于 2020-01-27 16:42:25
1.线程安全: 当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方法进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象就是线程安全的。 2.Java语言中的线程安全  根据线程安全的安全程度由强到弱来排序,我们可以把Java语言中各种操作共享的数据分为以下5类:不可变、绝对线程安全、相对线程安全、线程兼容和线程对立。    1)不可变: 不可变的对象一定是线程安全的;Java语言中,如果共享数据是一个基本数据类型,那么只要在定义时使用final关键字修饰它就可以保证它是不可变的。如果共享数据是一个对象,那就需要保证对象的行为不会对其状态产生任何影响,即把对象中带有状态的变量都声明为final,这样在构造函数结束之后,它就是不可变的。    2)绝对线程安全: 就是一个类在任何运行时环境下,调用者都不需要任何额外的同步措施。在Java API中标注自己是线程安全的类,大多数都不是绝对线程安全的。    3)相对线程安全: 就是我们通常所讲的线程安全,它需要保证对这个对象单独的操作是线程安全的,我们在调用时不需要做额外的保障措施。但对于一些特定顺序的连续调用,就可能需要在调用端使用额外的同步手段来保证调用的正确性。    4)线程兼容: 指对象本身并不是线程安全的

Java多线程

99封情书 提交于 2020-01-27 05:11:11
一、停止线程(interrupt)   停止线程意味着在线程处理玩任务之前停掉正在做的操作,Java之前的版本提供Thread.stop()方法,但这个方法是不安全的,已被废弃。 1、目前停止线程主要有两种方式:   1)使用退出标志   2)使用interrupt方法中断线程。此方式需要使用interrupt对要中断的线程进行标记,通过interrupted或isInterrupted方法结合相应逻辑(break等操作)实现线程中断。 2、interrupt、interrupted、isInterrupted区别   1)interrupt标记线程为中断状态   2)interrupted测试当前线程是否中断,并清除中断标记为false   3)isInterrupted测试线程是否中断 3、使用interrupt方法中断线程实例 public class InterruptThread extends Thread { @Override public void run() { for(int i = 0; i < 50000; i++) { System.out.println("i = " + i); //if(this.isInterrupted()) { if(Thread.interrupted()) { System.out.println("thread stop

53JAVA多线程----线程安全

坚强是说给别人听的谎言 提交于 2020-01-26 19:43:46
1.线程安全 如果有多个线程在同时运行,而这些线程可能会同时运次这段代码。程序每次运行结果和单线程运行结果是一样的,而且其他的变量的值也和预期的结果是一样的,就是线程安全的。 下来通过一个案例,演示线程的安全问题: 电影院要卖票,我们模拟电影院的卖票过程,假设要播放的电影是“囧囧”,本次电影的座位共100个 我们来模拟电影院的售票窗口,实现多个窗口同时卖卖“囧囧”这场电影票(多个窗口一起卖这100张票) 需要窗口,采用线程对象来模拟;需要票,Runnable接口子类来模拟 模拟票 public class Ticket implements Runnable { private int ticket = 100 ; /* * 执行卖票操作 */ @Override public void run ( ) { //每个窗口卖票的操作 //窗口 永远开启 while ( true ) { if ( ticket > 0 ) { //有票 可以卖 //出票操作 //使用sleep模拟一下出票时间 try { Thread . sleep ( 100 ) ; } catch ( InterruptedException e ) { // TODO Auto‐generated catch block e . printStackTrace ( ) ; } //获取当前线程对象的名字

synchronized底层实现

不打扰是莪最后的温柔 提交于 2020-01-26 17:58:08
1、锁升级的过程   当多个线程同时竞争一个对象监视器时:当前 对象结构 中的 mark word 中是否是 当前线程id ,如果是则当前线程获得 偏向锁 。 如果不是,则通过CAS将当前线程id置换到mark word中,如果成功则获得偏向锁,如果不成功则说明有竞争,升级为轻量级锁。 后续再通过CAS将 线程的指针 放到mark word中,若成功则获得锁,否则升级为 自旋锁 。自旋锁仍然为轻量级锁,不成功升级为重量级锁。 对象结构 :在JVM中,对象在内存中的布局分为三块区域:对象头、实例数据和对齐填充 mark word :存在于对象头中,存储对象的hashcode,锁标识,分代年龄及GC标识等信息 由上图可以看出,为何偏向锁是将线程id放入mark word,轻量级锁为何将锁的指针放入mark word。 偏向锁 :指偏向于第一个访问的线程,在运行过程中,同步锁没有竞争,则会在这个线程的头部加一个标志位,标记为偏向锁,如果发生竞争则会升级为轻量级锁或者重量级锁 自旋锁 :线程请求不到对象锁时不会堵塞,只是自己循环一下等待对象锁的释放。 因为线程的堵塞和唤醒非常消耗内存 ,所以自旋锁可以很好的优化这个问题。 但它只适合等待时间比较短的,而且并发量不高的场景。 2、升级到重量级锁后,如何运行 当多线程竞争时,不满足的条件的线程会进入同步队列,满足条件后进入同步代码