synchronized

面试刷题16:synchronized和ReentrantLock的区别?

こ雲淡風輕ζ 提交于 2020-03-27 20:23:48
java并发编程是程序员基本技能。 我是李福春,我在准备面试,今天的题目是: synchronized和ReentrantLock的区别? 这两货都是java提供的同步机制,提供了互斥语义和可见性,当一个线程获得资源之后,其它竞争资源的线程必须等待或者堵塞。 区别如下: 线程安全 线程安全说的是多线程场景下,共享可修改状的数据的正确性。 从语义来看,保证线程安全的方法有2: 1, 封装起来,数据不共享,私有化。 2, 数据不可修改,自然不存在线程不安全。final,immutable; 线程安全的3个特性: 隔离性: 相关操作不会被其它线程干扰 顺序性: 线程内的串行语义,避免指令重排; 可见性: 线程的本地变量修改应该反馈到主内存上,使用volatile关键字。 先来看一个线程不安全的例子: package org.example.mianshi.concurrent; /** * 线程不安全例子,共享数据sharedState * @author lifuchun */ public class ThreadSafeSample { public int sharedState; public void nonSafeAction() { while (sharedState < 100000) { int former = sharedState++; int latter

面试刷题16:synchronized和ReentrantLock的区别?

你说的曾经没有我的故事 提交于 2020-03-27 19:16:50
3 月,跳不动了?>>> <br /> <br /> <br />java并发编程是程序员基本技能。<br /> <br />我是李福春,我在准备面试,今天的题目是:<br /> <br />synchronized和ReentrantLock的区别?<br /> <br />这两货都是java提供的同步机制,提供了互斥语义和可见性,当一个线程获得资源之后,其它竞争资源的线程必须等待或者堵塞。<br /> <br />区别如下:<br /> <br /> <br /> <br /> 线程安全 <br /> <br />线程安全说的是多线程场景下,共享可修改状的数据的正确性。<br /> <br />从语义来看,保证线程安全的方法有2:<br />1, 封装起来,数据不共享,私有化。<br />2, 数据不可修改,自然不存在线程不安全。final,immutable;<br /> <br />线程安全的3个特性:<br />隔离性: 相关操作不会被其它线程干扰<br />顺序性: 线程内的串行语义,避免指令重排;<br />可见性: 线程的本地变量修改应该反馈到主内存上,使用volatile关键字。<br /> <br /> <br />先来看一个线程不安全的例子:<br /> package org.example.mianshi.concurrent; /** * 线程不安全例子

Java Thread(线程)案例详解sleep和wait的区别

自作多情 提交于 2020-03-27 18:16:54
Java Thread(线程)案例详解sleep和wait的区别 上次对Java Thread有了总体的概述与总结,当然大多都是理论上的,这次我将详解Thread中两个常用且容易疑惑的方法、并通过实例代码进行解疑。。。 F 区别 sleep()方法   sleep()使当前线程进入停滞状态(阻塞当前线程),让出CUP的使用、目的是不让当前线程独自霸占该进程所获的CPU资源,以留一定时间给其他线程执行的机会;    sleep()是Thread类的Static(静态)的方法;因此他不能改变对象的机锁,所以当在一个Synchronized块中调用Sleep()方法是,线程虽然休眠了,但是对象的机锁并木有被释放,其他线程无法访问这个对象(即使睡着也持有对象锁)。   在sleep()休眠时间期满后,该线程不一定会立即执行,这是因为其它线程可能正在运行而且没有被调度为放弃执行,除非此线程具有更高的优先级。    wait()方法   wait()方法是Object类里的方法;当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时失去(释放)了对象的机锁(暂时失去机锁,wait(long timeout)超时时间到后还需要返还对象锁);其他线程可以访问;   wait()使用notify或者notifyAlll或者指定睡眠时间来唤醒当前等待池中的线程。   wiat(

Java synchronized与Lock初步解读

£可爱£侵袭症+ 提交于 2020-03-27 18:15:30
3 月,跳不动了?>>> Java中有两种加锁的方式:一种是用 synchronized关键字 ,另一种是用 Lock接口 的实现类。 形象地说,synchronized关键字是 自动档 ,可以满足一切日常驾驶需求。但是如果你想要玩漂移或者各种骚操作,就需要 手动档 了——各种Lock的实现类。 所以如果你只是想要简单的加个锁,对性能也没什么特别的要求,用synchronized关键字就足够了。自Java 5之后,才在java.util.concurrent.locks包下有了另外一种方式来实现锁,那就是Lock。 也就是说,synchronized是Java语言内置的关键字,而Lock是一个接口 ,这个接口的实现类在代码层面实现了锁的功能,具体细节不在本文展开,有兴趣可以研究下AbstractQueuedSynchronizer类,写得可以说是牛逼爆了。 其实只需要关注三个类就可以了:ReentrantLock类、ReadLock类、WriteLock类。 ReentrantLock、ReadLock、WriteLock 是Lock接口最重要的三个实现类。对应了“可重入锁”、“读锁”和“写锁”,后面会讲它们的用途。 ReadWriteLock其实是一个工厂接口,而ReentrantReadWriteLock是ReadWriteLock的实现类

多线程之wait,notify,volatile,synchronized,sleep

浪尽此生 提交于 2020-03-27 17:32:08
  最近在学习多线程,现在进行总结一下吧。首先要了解一下以下几个名词。   (1)wait:当线程调用wait()方法时,当前该线程会进入阻塞状态,且 释放锁 ,使用wait方法的时候, 必须配合synchronized使用 。   (2)notify:当线程调用notify()方法时,会唤醒一个处于等待该对象锁的线程, 不释放锁 ,使用notify方法的时候, 必须配合synchronized使用 。   (3)sleep:当线程调用sleep()方法时,会让出CPU执行权, 不释放锁 。当指定的时间到了后,会自动恢复运行状态。   (4)volatile:可见性,它修饰的成员变量在每次被线程访问时,都强迫从内存中重读该成员变量的值;而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存,这样在任何时刻两个不同线程总是看到某一成员变量的同一个值,这就是保证了可见性。( 当多个线程操作同一个成员变量的时候,为了提高效率,JVM为每个线程单独复制了一份 ,这样会导致各个线程读取的数据出现脏数据,所以使用volatile关键字可以解决脏数据问题)。   (5)synchronized:synchronized为一段操作或内存进行加锁,它具有互斥性。当线程要操作被synchronized修饰的内存或操作时, 必须首先获得锁才能进行后续操作

面试刷题15:synchronized底层是如何实现的?

你说的曾经没有我的故事 提交于 2020-03-27 17:25:22
所有的同步场景都是基于锁。锁在并发编程中发挥重要作用。 我是李福春,我在准备面试,今天的题目是: synchronized底层是如何实现的? 答: synchronized是在底层的jvm中实现的,即c++写的,synchronized的实现是基于一对monitorenter, monitorexit指令实现的,monitor对象是同步的基本实现单元。 在java6中,monitor依靠操作系统提供的内部互斥锁,需要在用户态空间和内核态空间切换,所以同步操作是一个比较重的操作,开销比较大。 在java7之后,monitor有三种不同的实现,即偏斜锁,轻量级锁,重量级锁。 基于对象头的markword,标记上偏向的线程id, 在没有竞争的条件下,使用的是偏斜锁; 当有多个线程来竞争偏斜锁,基于cas对对象头的markword来进行竞争,如果拿到了,升级为轻量级锁。 没拿到则升级为重量级锁; 锁降级发生在jvm进入安全点检查的时候,对monitor进行降级。 synchronized底层实现 对象头结构: sharedRuntime.cpp 解释器和编译器的运行时基类。 ```cpp Handle h_obj(THREAD, obj); if (UseBiasedLocking) { // Retry fast entry if bias is revoked to avoid

试题

牧云@^-^@ 提交于 2020-03-27 03:29:55
讲一讲并行和并发 进程的线程的区别 进程是资源分配的最小单位,线程是程序执行的最小单位。 进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。 线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。 但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。 进程间通信的有哪几种方式 管道(Pipe)及有名管道(named pipe): 信号量 共享内存 信号(Signal) 报文(Message)队列(消息队列) 套接字 线程间资源可以共享吗,进程间呢 Java并发,说一说了解哪些,volatie个synchronized的 volatile本质是告诉JVM当前变量在寄存器中的值是不确定的,需要从主存中读取。synchronized则是锁定当前变量,只有当前线程可以访问该变量,其它线程被阻塞。 volatile仅能使用在变量级别,synchronized则可以使用在变量、方法。

面试必备之乐观锁与悲观锁

醉酒当歌 提交于 2020-03-25 19:09:34
何谓悲观锁与乐观锁 乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。 悲观锁 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。 乐观锁 总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。 两种锁的使用场景 从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候

高并发和多线程(1)

廉价感情. 提交于 2020-03-24 18:17:12
进程和线程 进程:一个启动正在运行的程序称之为进程。线程:是 操作系统 能够进行运算 调度 的最小单位。它包含在进程中,是进程执行的最小单元,是一个程序的运行轨迹。 一、synchronized 底层实现原理:synchronized 底层字节码文件是通过monitor指令控制线程,同步代码块儿在获取线程的开始部位添加一个monitorrenter指令,在结束部位添加一个monitorexit指令,入下图所示(代码可以通过javap命令编译查看)。为什么最后会有monitorexit命令,是为了防止中间出现异常,而最后能给正常退出,避免造成死锁。 synchronized 是可重入的锁,可重入锁的意思就是,同一个线程进入同步代码块儿是被允许的,并且在父子类之间也是可重入的。底层原理是当线程获取该锁时,计数器加一,再次获得该锁时继续加一,释放锁时,计数器减一,当计数器值为0时,表明该锁未被任何线程所持有,其它线程可以竞争获取锁。 锁优化 在一个线程要想获取锁就需要向系统内核申请资源,在这个过程是非常消耗资源的,应该是为了避免过度的申请消耗,从而在对象做了手脚;一个java对象由对象标记,类型指针,真实数据,内存补齐四部分组成: 对象标记也称Mark Word字段,存储当前对象的一些运行时数据。 类型指针,JVM根据该指针确定该对象是哪个类的实例化对象。 真实数据自然是对象的属性值。

深入理解Synchronized

拥有回忆 提交于 2020-03-23 22:13:08
3 月,跳不动了?>>> 目前在Java中存在两种锁机制:synchronized和Lock,Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug Lea。本文并不比较synchronized与Lock孰优孰劣,只是介绍二者的实现原理。 数据同步需要依赖锁,那锁的同步又依赖谁?synchronized给出的答案是在软件层面依赖JVM,而Lock给出的方案是在硬件层面依赖特殊的CPU指令,大家可能会进一步追问:JVM底层又是如何实现synchronized的? 本文所指说的JVM是指Hotspot的6u23版本,下面首先介绍synchronized的实现: synrhronized关键字简洁、清晰、语义明确,因此即使有了Lock接口,使用的还是非常广泛。其应用层的语义是可以把任何一个非null对象作为"锁",当synchronized作用在方法上时,锁住的便是对象实例(this);当作用在静态方法时锁住的便是对象对应的Class实例,因为Class数据存在于永久带,因此静态方法锁相当于该类的一个全局锁;当synchronized作用于某一个对象实例时,锁住的便是对应的代码块。在HotSpot JVM实现中,锁有个专门的名字:对象监视器。 1. 线程状态及状态转换 当多个线程同时请求某个对象监视器时,对象监视器会设置几种状态用来区分请求的线程: