精华内容
下载资源
问答
  • 在调用 wait()之前,线程必须要获得该对象的对象级别,即只能在同步方法或同步块中调用 wait()方法。进入 wait()方法后,当前线程释放。在从 wait()返回前,线程与其他线程竞争重新获得。如果调用 wait()时,...

    wait()

    该方法用来将当前线程置入休眠状态,直到接到通知或被中断为止。在调用 wait()之前,线程必须要获得该对象的对象级别锁,即只能在同步方法或同步块中调用 wait()方法。进入 wait()方法后,当前线程释放锁。在从 wait()返回前,线程与其他线程竞争重新获得锁。如果调用 wait()时,没有持有适当的锁,则抛出 IllegalMonitorStateException,它是 RuntimeException 的一个子类,因此,不需要 try-catch 结构。

    notify()

    该方法也要在同步方法或同步块中调用,即在调用前,线程也必须要获得该对象的对象级别锁,的如果调用 notify()时没有持有适当的锁,也会抛出 IllegalMonitorStateException。

    该方法用来通知那些可能等待该对象的对象锁的其他线程。如果有多个线程等待,则线程规划器任意挑选出其中一个 wait()状态的线程来发出通知,并使它等待获取该对象的对象锁(notify 后,当前线程不会马上释放该对象锁,wait 所在的线程并不能马上获取该对象锁,要等到程序退出 synchronized 代码块后,当前线程才会释放锁,wait所在的线程也才可以获取该对象锁),但不惊动其他同样在等待被该对象notify的线程们。当第一个获得了该对象锁的 wait 线程运行完毕以后,它会释放掉该对象锁,此时如果该对象没有再次使用 notify 语句,则即便该对象已经空闲,其他 wait 状态等待的线程由于没有得到该对象的通知,会继续阻塞在 wait 状态,直到这个对象发出一个 notify 或 notifyAll。这里需要注意:它们等待的是被 notify 或 notifyAll,而不是锁。这与下面的 notifyAll()方法执行后的情况不同。

    notifyAll()

    该方法与 notify ()方法的工作方式相同,重要的一点差异是:

    notifyAll 使所有原来在该对象上 wait 的线程统统退出 wait 的状态(即全部被唤醒,不再等待 notify 或 notifyAll,但由于此时还没有获取到该对象锁,因此还不能继续往下执行),变成等待获取该对象上的锁,一旦该对象锁被释放(notifyAll 线程退出调用了 notifyAll 的 synchronized 代码块的时候),他们就会去竞争。如果其中一个线程获得了该对象锁,它就会继续往下执行,在它退出 synchronized 代码块,释放锁后,其他的已经被唤醒的线程将会继续竞争获取该锁,一直进行下去,直到所有被唤醒的线程都执行完毕。

    总结

    如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。

    当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。

    优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

    展开全文
  • 1. 如何实现乐观(CAS)?如何避免ABA问题?答:1)读取内存值的方式实现了乐观(比如:SVN系统),方法:第一,比较内存值和期望值;第二,替换内存值为要替换值。2)带参数版本来避免aba问题,在读取和替换的时候...

    1. 如何实现乐观锁(CAS)?如何避免ABA问题?

    答:1)读取内存值的方式实现了乐观锁(比如:SVN系统),方法:第一,比较内存值和期望值;第二,替换内存值为要替换值。

    2)带参数版本来避免aba问题,在读取和替换的时候进行判定版本是否一致

    1363269437_5451.jpg

    2. 读写锁可以用于什么应用场景?

    答: 读写锁可以用于 “多读少写” 的场景,读写锁支持多个读操作并发执行,写操作只能由一个线程来操作

    ReadWriteLock对向数据结构相对不频繁地写入,但是有多个任务要经常读取这个数据结构的这类情况进行了优化。ReadWriteLock使得你可以同事有多个读取者,只要它们都不试图写入即可。如果写锁已经被其他任务持有,那么任何读取者都不能访问,直至这个写锁被释放为止。

    ReadWriteLock 对程序心性能的提高受制于如下几个因素也还有其他等等的因素。

    1)数据被读取的频率与被修改的频率相比较的结果。

    2)读取和写入的时间

    3)有多少线程竞争

    4)是否在多处理机器上运行

    3. 什么时候应该使用可重入锁?

    答:重入锁指的是在某一个线程中可以多次获得同一把锁,在线程中多次操作有锁的方法。

    4. 什么场景下可以使用volatile替换synchronized?

    答: 只需要保证共享资源的可见性的时候可以使用volatile替代,synchronized保证可操作的原子性一致性和可见性。volatile适用于新值不依赖于就值的情形。

    volatile是java提供的一种同步手段,只不过它是轻量级的同步,为什么这么说,因为volatile只能保证多线程的内存可见性,不能保证多线 程的执行有序性。而最彻底的同步要保证有序性和可见性,例如synchronized。任何被volatile修饰的变量,都不拷贝副本到工作内存,任何 修改都及时写在主存。因此对于Valatile修饰的变量的修改,所有线程马上就能看到,但是volatile不能保证对变量的修改是有序的。volatile存在的意义是,任何线程对某个变量的修改,都会马上被其他线程读取到,因为直接操作主存, 没有线程对工作内存和主存的同步。所以,volatile的使用场景是有限的,在有限的一些情形下可以使用 volatile 变量替代锁(synchronized)。

    要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:

    1)对 变量的写操作不依赖于当前值。

    2)该变量没有包含在具有其他变量的不变式中

    展开全文
  • 俗话讲,3月不跳槽,5月徒伤悲,到了八九月,就只能惦记着年终奖,又害怕新机会鸡飞蛋打 :)今天主要内容是java的线程部分和java。1.什么是线程?进程和线程的关系是什么?线程可定义为进程内的一个执行单位,...

    9696551d217240723741bb57e88e4e6c.png

    俗话讲,3月不跳槽,5月徒伤悲,到了八九月,就只能惦记着年终奖,又害怕新机会鸡飞蛋打 :)

    今天主要内容是java的线程部分和java的锁。

    1.什么是线程?进程和线程的关系是什么?

    线程可定义为进程内的一个执行单位,或者定义为进程内的一个可调度实体。 在具有多线程机制的操作系统中,处理机调度的基本单位不是进程而是线程。

    一个进程可以有多个线程,而且至少有一个可执行线程。

    简单的说,进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫做轻量级进程。

    线程和进程的关系:

    线程是进程的一个组成部分.

    进程的多个线程都在进程地址空间活动.

    系统资源是分配给进程的,线程需要资源时,系统从进程的资源里分配给线程.

    计算机调度的基本单位是线程.

    线程上下文的切换比进程上下文切换要快很多

    进程切换时,涉及到当前进程的CPU环境的保存和新被调度运行进程的CPU环境的设置。

    线程切换仅需要保存和设置少量的寄存器内容,不涉及存储管理方面的操作。

    2.什么是线程安全和线程不安全?

    简单的说,加锁的就是线程安全的,不加锁的是线程不安全的

    线程安全:当多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问,直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

    线程不安全:就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据

    如果代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

    线程安全问题都是由全局变量及静态变量引起的。 若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

    3.什么是多线程?

    多线程就是多个线程同时运行或交替运行。

    如果是单核CPU则是顺序执行,也就是交替运行。

    如果是多核CPU,因为每个CPU有自己的运算器,所以在多个CPU中可以同时运行。

    4.为什么要有多线程?

    使用线程可以把占据长时间的程序中的任务放到后台去处理。

    用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度。

    程序的运行速度可能加快。

    dc30074dc609dbac6e13d3b862c5e291.png

    5.Java多线程有哪几类

    用户线程:运行在前台,执行具体的任务,如程序的主线程、连接网络的子线程等都是用户线程守护线程:运行在后台,为其他前台线程服务.一旦所有用户线程都结束运行,守护线程会随JVM一起结束工作6、什么是多线程上下文切换

    多线程的上下文切换是指CPU控制权由一个已经正在运行的线程切换到另外一个就绪并等待获取CPU执行权的线程的过程。

    7.创建线程有几种不同的方式?

    有三种方式可以用来创建线程:

    继承Thread类实现Runnable接口应用程序可以使用Executor框架来创建线程池通常用实现Runnable接口这种方式创建线程,因为这不需要继承Thread类。

    8.Thread 类中的start() 和 run() 方法有什么区别?

    start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。

    当调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。

    9.直接调用start()方法时和直接调用run()方法有什么区别?

    当我们new一个Thread,线程进入了新建状态;调用start()方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。

    start()会执行线程的相应准备工作,然后自动执行run()方法的内容,这是真正的多线程工作。

    而直接执行run()方法,会把run方法当成一个main线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。

    因此,调用start方法方可启动线程并使线程进入就绪状态,而run方法只是thread的一个普通方法调用,还是在主线程里执行。

    10.对ThreadLocal的理解

    ThreadLocal是一个创建线程局部变量的类。通常情况下我们创建的变量,可以被多个线程访问并修改,通过ThreadLocal创建的变量只能被当前线程访问。因为ThreadLocal的值是放入了当前线程的一个ThreadLocalMap实例中,所以只能在本线程中访问,其他线程无法访问。

    简单说,ThreadLocal就是一种以空间换时间的做法。在每个Thread里面维护了一个ThreadLocal.ThreadLocalMap把数据进行隔离,数据不共享,自然就没有线程安全方面的问题了.

    11.ThreadLocal内部实现

    ThreadLocal提供了set和get方法.

    set方法会先获取当前线程,然后用当前线程作为句柄,获取ThreadLocaMap对象,并判断该对象是否为空,如果为空则创建一个,并设置值,不为空则直接设置值。

    ThreadLocal并不会导致内存泄露,因为ThreadLocalMap中的key存储的是ThreadLocal实例的弱引用,因此如果应用使用了线程池,即便之前的线程实例处理完之后出于复用的目的依然存活,也不会产生内存泄露。

    12.什么是线程安全?

    当多个线程访问某个类时,不管运行时环境采用何种调度方式或者线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为。

    线程安全的核心是“正确性”,也就是说当多个线程访问某个类时,能够得到预期的结果,那么就是线程安全的。

    791f8d292b53b6f052f86f6067cfd8a0.png

    13、如何在两个线程间共享数据

    通过在线程之间共享对象就可以了,然后通过wait/notify/notifyAll、await/signal/signalAll进行唤起和等待。

    比如说:阻塞队列BlockingQueue就是为线程之间共享数据而设计的

    14、生产者消费者模型的作用是什么?

    提高效率:通过平衡生产者的生产能力和消费者的消费能力来提升整个系统的运行效率,这是生产者消费者模型最重要的作用

    解耦:这是生产者消费者模型附带的作用,解耦意味着生产者和消费者之间的关联少,耦合越少就越可以独自发展而不需要收到相互的制约

    15、java中的++操作符是线程安全的么?

    不是线程安全的操作。

    它涉及到多个指令,如读取变量值,增加,然后存储回内存,这个过程可能会出现多个线程交差

    展开全文
  • 一、写在前面上篇文章(《大白话聊聊Java并发面试问题之谈谈你对AQS的理解?》)聊了一下java并发包中的AQS的工作原理,也间接说明了ReentrantLock的工作原理。这篇文章接着来聊一个话题,java并发包中的公平与非...

    一、写在前面

    上篇文章(《大白话聊聊Java并发面试问题之谈谈你对AQS的理解?》)聊了一下java并发包中的AQS的工作原理,也间接说明了ReentrantLock的工作原理。

    这篇文章接着来聊一个话题,java并发包中的公平锁与非公平锁有啥区别?二、什么是非公平锁?

    先来聊聊非公平锁是啥,现在大家先回过头来看下面这张图。

    AAffA0nNPuCLAAAAAElFTkSuQmCC

    如上图,现在线程1加了锁,然后线程2尝试加锁,失败后进入了等待队列,处于阻塞中。然后线程1释放了锁,准备来唤醒线程2重新尝试加锁。

    注意一点,此时线程2可还停留在等待队列里啊,还没开始尝试重新加锁呢!

    然而,不幸的事情发生了,这时半路杀出个程咬金,来了一个线程3!线程3突然尝试对ReentrantLock发起加锁操作,此时会发生什么事情?

    很简单!线程2还没来得及重新尝试加锁呢。也就是说,还没来得及尝试重新执行CAS操作将state的值从0变为1呢!线程3冲上来直接一个CAS操作,尝试将state的值从0变为1,结果还成功了!

    一旦CAS操作成功,线程3就会将“加锁线程”这个变量设置为他自己。给大家来一张图,看看这整个过程:

    AAffA0nNPuCLAAAAAElFTkSuQmCC

    明明人家线程2规规矩矩的排队领锁呢,结果你线程3不守规矩,线程1刚释放锁,不分青红皂白,直接就跑过来抢先加锁了。

    这就导致线程2被唤醒过后,重新尝试加锁执行CAS操作,结果毫无疑问,失败!

    原因很简单啊!因为加锁CAS操作,是要尝试将state从0变为1,结果此时state已经是1了,所以CAS操作一定会失败!

    一旦加锁失败,就会导致线程2继续留在等待队列里不断的等着,等着线程3释放锁之后,再来唤醒自己,真是可怜!先来的线程2居然加不到锁!

    同样给大家来一张图,体会一下线程2这无助的过程:

    AAffA0nNPuCLAAAAAElFTkSuQmCC

    上述的锁策略,就是所谓的非公平锁!

    如果你用默认的构造函数来创建ReentrantLock对象,默认的锁策略就是非公平的。

    在非公平锁策略之下,不一定说先来排队的线程就就先会得到机会加锁,而是出现各种线程随意抢占的情况。

    那如果要实现公平锁的策略该怎么办呢?也很简单,在构造ReentrantLock对象的时候传入一个true即可:

    ReentrantLock lock = new ReentrantLock(true)

    此时就是说让他使用公平锁的策略,那么公平锁具体是什么意思呢?三、什么是公平锁?

    咱们重新回到第一张图,就是线程1刚刚释放锁之后,线程2还没来得及重新加锁的那个状态。

    AAffA0nNPuCLAAAAAElFTkSuQmCC

    同样,这时假设来了一个线程3,突然杀出来,想要加锁。

    如果是公平锁的策略,那么此时线程3不会跟个愣头青一样盲目的直接加锁。

    他会先判断一下:咦?AQS的等待队列里,有没有人在排队啊?如果有人在排队的话,说明我前面有兄弟正想要加锁啊!

    如果AQS的队列里真的有线程排着队,那我线程3就不能跟个二愣子一样直接抢占加锁了。

    因为现在咱们是公平策略,得按照先来后到的顺序依次排队,谁先入队,谁就先从队列里出来加锁!

    所以,线程3此时一判断,发现队列里有人排队,自己就会乖乖的排到队列后面去,而不会贸然加锁!

    同样,整个过程我们用下面这张图给大家直观的展示一下:

    AAffA0nNPuCLAAAAAElFTkSuQmCC

    上面的等待队列中,线程3会按照公平原则直接进入队列尾部进行排队。

    接着,线程2不是被唤醒了么?他就会重新尝试进行CAS加锁,此时没人跟他抢,他当然可以加锁成功了。

    然后呢,线程2就会将state值变为1,同时设置“加锁线程”是自己。最后,线程2自己从等待队列里出队。

    整个过程,参见下图:

    AAffA0nNPuCLAAAAAElFTkSuQmCC

    这个就是公平锁的策略,过来加锁的线程全部是按照先来后到的顺序,依次进入等待队列中排队的,不会盲目的胡乱抢占加锁,非常的公平。四、小结

    好了,通过画图和文字分析,相信大家都明白什么是公平锁,什么是非公平锁了!

    不过要知道java并发包里很多锁默认的策略都是非公平的,也就是可能后来的线程先加锁,先来的线程后加锁。

    而一般情况下,非公平的策略都没什么大问题,但是大家要对这个策略做到心里有数,在开发的时候,需要自己来考虑和权衡是要用公平策略还是非公平策略。

    石杉的架构笔记(id:shishan100)

    作者:中华石杉,多年BAT架构经验倾囊相授

    展开全文
  • 面试题:你对java中的有所了解么?有哪几种?它们有什么区别?你来说一下。(学习视频分享:java视频教程)解答:大致可以分为这几点:是什么,有什么用,有哪几种的区别。一:是什么,有什么用?主要...
  • 1. 什么是可重入(ReentrantLock)?答: java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现。这就为 Lock 的多种实现留下了空间,各种实现...
  • 1. 如何实现乐观(CAS)?如何避免ABA问题?答:1)读取内存值的方式实现了乐观(比如:SVN系统),方法:第一,比较内存值和期望值;第二,替换内存值为要替换值。2)带参数版本来避免aba问题,在读取和替换的时候...
  • JAVA 常见面试题

    2021-01-07 16:57:05
    每个 Java 对象都有一个关联的 monitor,使用 synchronized 时 JVM 会根据使用环境找到对象的 monitor,根据 monitor 的状态进行加解锁的判断。如果成功加锁就成为该 monitor 的唯一持有者,monitor 在被释放前不能...
  • 面试题 加锁和释放没有配对 自动释放导致的重复逻辑执行的问题 有什么方法来发现和解决这两种问题? 讲解 释放和重复执行问题:建议使用synchronized,在JDK1.6后,synchronized与Lock性能上差距很小了...
  • 这系列相关博客,参考慕课专栏 面试官系统精讲Java源码及大厂真题 下方是本专栏 GitHub 地址: 源码解析:...Java源码解析和面试题 - 只求问倒:连环相扣系列锁面试题1 AQS 相关面试题2 AQS 子...
  • java锁面试题

    千次阅读 2016-08-09 08:21:11
    另外的的线程完全可以访问没有锁定的方法,例如在一个线程中将某个方法锁定,但是...import java.io.*; import java.lang.*; import java.util.*; public class hehe implements Runnable{ public int b = 100; pu
  • 答:最大区别是等待时wait会释放,而sleep会一直持有,wait通常用于线程时交互,sleep通常被用于暂停执行。2、java中volatile和synchronized有什么区别?1.volatile本质是在告诉jvm当前变量在寄存器(工作内存...
  • 面试题包含了不同技术层面的面试问题,同时也能对一些没有面试开发经验的小白给予不可估量的包装, 让你的薪水绝对翻倍, 本人亲试有效.Java面试题84集、java面试专属及面试必问课程,所有的面试题有视屏讲解, 解答方案....
  • 面试官:sychronized关键字有哪些特性?应聘者:可以用来修饰方法;...内置Java中每一个对象都可以作为同步的,那么这些就被称为内置。线程进入同步代码块或方法的时候会自动获得该,...
  • Java 多线程 并发 Java线程面试题

    千次阅读 2018-05-12 00:02:12
    1) 什么是线程?线程是操作系统能够进行运算调度的最小单位,它被...Java在语言层面对多线程提供了卓越的支持,它也是一个很好的卖点。2) 线程和进程有什么区别?线程是进程的子集,一个进程可以有很多线程,每条线...
  • Java基础面试题 1 jvm内存模型概述描述下常用的垃圾收集算法垃圾收集器机制 2 stringbuffer和stringbuilder的区别底层实现原理 3 concurrenthashmap底层实现和机制 4 arraylist与linklist的区别在遍历查找和增删改...
  • 如果说快速理解多线程有什么捷径的话,那本文介绍的各种无疑是其中之一,它不但为我们开发多线程程序提供理论支持,还是面试中经常被问到的核心面试题之一。因此下面就让我们一起深入地学习一下这些吧。乐观和...
  • synchronized和lock的区别:类别synchronizedlock存在层次java的关键字,在jvm层面上是一个类的释放1、以获取的线程执行完同步代码,释放2、线程执行发生异常,jvm会让线程释放在finally中必须释放,不然...
  • 减少持有时间减小粒度分离粗化消除2、虚拟机是怎么优化的?偏向轻量级自旋3、javac编译可分为哪三个步骤?解析与填充符号表过程;插入式注解处理器的注解处理过程;语义分析与字节码生成过程。4、...
  • 不错的面试题4.从没有看到这么通俗易懂的sping的解析6. --》非安全 数据结构(map list 堆 栈),是因为1)其数据的操作方法,不是原子性的(多行代码,某个线程没有运行结束,其他线程进来了)2)另外就是多线程同时...
  • Java公平和非公平概念如何创建两者区别外话可重入和递归ReentrantLock概念代码作用可重入验证证明ReentrantLock自旋概念优缺点手写自旋独占(写) / 共享(读) / 互斥概念为什么会...
  • 阿里面试题 1. 二叉树的遍历方式,前序、中序、后序和层序 2. volatile关键字 3. synchronized 4. concurrentHashMap 5. 的优化策略 6. 操作系统 项目部分 1、缓存的使用,如果现在需要实现一个简单的缓存,供搜索...
  • 虽说已经是金三银四末期了,但陆续来面试的Java程序员也不少...Java实现机制,使用场景分析ReentranLock 源码,设计原理,整体过程volatile 的实现原理AQS 的实现过程……如果你仔细观察的话,上面的面试题都是...
  • java锁机制的面试题

    2020-04-18 16:10:52
    提供了多种实现 Java 线程安全的方式: 最简单的方式,使用 Synchronization 关键字 使用 java.util.concurrent.atomic 包中的原子类,例如 AtomicInteger 使用 java.util.concurrent.locks 包中的 ...
  • 快手Java一面(一个小时十分钟) 1.自我介绍 2.说说B+树和B树的区别,优缺点等? 3聊聊Spring,主要IOC等等 4多线程JUC包下的一些常见的类,比如CountDownLatch、Semaphore等 5.的概念,相关的关键字...
  • java 关于常见面试题

    万次阅读 2019-02-27 14:22:17
    给对象加锁(可以理解为给这个对象的内存上,注意 只是这块内存,其他同类对象都会有各自的内存),这时候在其他一个以上线程中执行该对象的这个同步方法(注意:是该对象)就会产生互斥 静态方法: 相当于在类上加锁(*....
  • 可重入:作用防止死锁 自旋 读写
  • Java有关面试题

    2020-08-31 21:02:05
    自旋(SpinLock): 当一个线程在获取的时候,如果已经被其他的线程获取,那么该线程就会进入循环等待的状态,然后在不停的询问是否成功的获取的资源,一直到获取的才会退出循环。通常在CAS(Compare and ...
  • 分布式分为分布式缓存(Redis)、分布式(Redis或Zookeeper)、分布式服务(Dubbo或SpringCloud)、分布式服务协调(Zookeeper)、分布式消息队列(Kafka、RabbitMq)、分布式Session、分布式事务、分布式搜索...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,233
精华内容 893
关键字:

java锁面试题

java 订阅