线程

面试刷题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

并发编程面试题

只愿长相守 提交于 2020-03-27 19:15:01
1.进程和线程还有协程之间的关系   进程:运行起来的程序。进程需要占用系统资源(内存,CPU)。进程是最小的系统资源分配单位,只是给线程提供执行环境。 由于一个进程产生一个进程地址空间,且进程地址空间相互独立,一个进程死亡,其他进程不会受到影响。   线程:LWP(light weight process)轻量级进程。线程是最小的执行单位。CPU分配时间轮片的对象。   协程:coroutine,也叫轻量级线程。 与传统的系统级线程和进程相比,携程最大的优势在于“轻量级”,可以轻松创建上万个而不会导致系统资源衰歇。 2.并发和并行之间的区别   并发:指统一时间内,宏观上处理多个任务   并行:指统一时间内,真正上处理多个任务 3.Java中多线程实现的方式   3.1 继承Thread类,重写run方法;   3.2 实现Runnable接口,重写run方法,实现Runnable接口的实现类的实例对象作为Thread构造函数的target   3.3 通过Callable和FutureTask创建线程   3.4 通过线程池创建线程 4.Callable和Future模式   4.1 Callable     在Java中,创建线程一般有两种方式,一种是继承Thread类,一种是实现Runnable接口。然而,这两种方式的缺点是在线程任务执行结束后,无法获取执行结果

JVM史上最最最完整深入解析(12000字噢)

空扰寡人 提交于 2020-03-27 18:12:07
3 月,跳不动了?>>> 点点这个链接免费获取: 【推荐】2020年最新Java电子书集合.pdf(吐血整理) >>> 工作之余,总结一下JVM相关知识。 Java运行时数据区: Java虚拟机在执行Java程序的过程中会将其管理的内存划分为若干个不同的数据区域,这些区域有各自的用途、创建和销毁的时间,有些区域随虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束来建立和销毁。Java虚拟机所管理的内存包括以下几个运行时数据区域,如图: 1、程序计数器:指向当前线程正在执行的字节码指令。线程私有的。 2、虚拟机栈:虚拟机栈是Java执行方法的内存模型。每个方法被执行的时候,都会创建一个栈帧,把栈帧压人栈,当方法正常返回或者抛出未捕获的异常时,栈帧就会出栈。(1)栈帧:栈帧存储方法的相关信息,包含局部变量数表、返回值、操作数栈、动态链接a、局部变量表:包含了方法执行过程中的所有变量。局部变量数组所需要的空间在编译期间完成分配,在方法运行期间不会改变局部变量数组的大小。b、返回值:如果有返回值的话,压入调用者栈帧中的操作数栈中,并且把PC的值指向 方法调用指令 后面的一条指令地址。c、操作数栈:操作变量的内存模型。操作数栈的最大深度在编译的时候已经确定(写入方法区code属性的max_stacks项中)。操作数栈的的元素可以是任意Java类型,包括long和double

java多线程解读一(基础篇)

允我心安 提交于 2020-03-27 17:32:42
一、线程的定义 每个应用程序内部都是由一个或多个的进程组成,而每个进程内部都是由许多具体的线程执行,所以,线程是每个程序执行的最小单位。 二、线程的实现 1.通过继承java.lang.Thread类、重写类中的run方法 class PrimeThread extends Thread {   long minPrime;   PrimeThread(long minPrime) {     this.minPrime = minPrime;   }   public void run() {      // compute primes larger than minPrime . . .   } } 然后通过创建线程对象,使线程就绪 PrimeThread p = new PrimeThread(143); p.start(); 2.通过实现java.lang.Runnable接口,实现类中的run方法 class PrimeRun implements Runnable {   long minPrime;   PrimeRun(long minPrime) {     this.minPrime = minPrime;   }   public void run() {     // compute primes larger than minPrime . . .   

多线程之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修饰的内存或操作时, 必须首先获得锁才能进行后续操作

Java 一些面试题(未完待续)

依然范特西╮ 提交于 2020-03-27 16:57:29
计算机网络 面试基础知识之计算机网络 基础知识 集合框架 多线程 Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别? leep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间, 将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复(线程回到就绪状态)。 wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lockpool),如果线程重新获得对象的锁就可以进入就绪状态 线程的sleep()方法和yield()方法有什么区别? ① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会; ② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态; ③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常; ④ sleep()方法比yield()方法

类初始化导致死锁

為{幸葍}努か 提交于 2020-03-27 14:30:42
3 月,跳不动了?>>> 本文来自 PerfMa社区,欢迎关注公众号 链接: https://club.perfma.com/article/61163 一张图简单描述死锁 如上图,Thread1 拿到了 object1,Thread2 拿到了 object2,但是现在 Thread1 需要拿到 object2 的锁才能继续往下,Thread2 又要拿到 object1 才能继续往下,于是哪个线程都无法得到满足继续往下来释放对方所需要的锁对象,从而造成了死锁。 概述 之前写过关于类加载死锁的文章“消失的死锁”,说的是类加载过程中发生的死锁,我们从线程dump里完全看不出死锁的迹象,但是确实发生了死锁,没了解的建议看看我公众号上相关的文章。 本文要说的是另外一个问题,之前在生产环境上碰到,是类初始化导致的死锁,恩,你没看错,确实是类初始化导致的死锁,我之前写过一篇文章,不可逆的类初始化过程,这篇文章可以助你了解类的初始化过程,另外也写过一篇JDK的sql设计不合理导致的驱动类初始化死锁问题,也是关于初始化死锁的,原因其实差不多,不过本文将这个问题描述的场景更加通用化了。 Demo 严格意义上说,这个Demo里提到的情况是其中一个简单的场景,和我们线上碰到的场景会有点出入,比这个会更复杂点。 为了让问题能重现,我选择了一个最简单的办法,就是debug,一般情况下,并发导致的问题

Redis与Memcached的区别

可紊 提交于 2020-03-27 12:15:31
3 月,跳不动了?>>> 传统MySQL+ Memcached架构遇到的问题   实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量的不断增加,和访问量的持续增长,我们遇到了很多问题:   1.MySQL需要不断进行拆库拆表,Memcached也需不断跟着扩容,扩容和维护工作占据大量开发时间。   2.Memcached与MySQL数据库数据一致性问题。   3.Memcached数据命中率低或down机,大量访问直接穿透到DB,MySQL无法支撑。   4.跨机房cache同步问题。   众多NoSQL百花齐放,如何选择    最近几年,业界不断涌现出很多各种各样的NoSQL产品,那么如何才能正确地使用好这些产品,最大化地发挥其长处,是我们需要深入研究和思考的问题,实 际归根结底最重要的是了解这些产品的定位,并且了解到每款产品的tradeoffs,在实际应用中做到扬长避短,总体上这些NoSQL主要用于解决以下几 种问题   1.少量数据存储,高速读写访问。此类产品通过数据全部in-momery 的方式来保证高速访问,同时提供数据落地的功能,实际这正是Redis最主要的适用场景。   2.海量数据存储,分布式系统支持,数据一致性保证,方便的集群节点添加/删除。   3

浅解多线程

时光毁灭记忆、已成空白 提交于 2020-03-27 10:17:15
1、进程和线程的区别:http://www.cnblogs.com/lmule/archive/2010/08/18/1802774.html 2、 新手学习多线程的详细思路和流程 :http://www.cnblogs.com/xiaoguangit/p/4991825.html 3、 我是一个线程 :http://kb.cnblogs.com/page/542462/ 4、 多线程编程基础知识 :http://www.cnblogs.com/cy163/archive/2006/11/02/547428.html 5、 浅解多线程 :http://www.cnblogs.com/knowledgesea/archive/2012/11/22/2780651.html 6、进程与线程的一个简单解释:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html 来源: https://www.cnblogs.com/JLZT1223/p/6139840.html

JVM笔记(一) Java内存区域

蓝咒 提交于 2020-03-27 08:38:33
Java 内存区域 总概 java虚拟机在执行java程序的过程中,会把它管理的内存划分为几个不同的数据区域。每当运行一个java程序时,就会启动一个虚拟机。 具体的区域如图所示: 同时,方法区 与 堆 是由所有线程共享的数据区;而 虚拟机栈、本地方法栈、程序计数器 则是被线程隔离的区域。 一、程序计数器 什么是程序计数器? 概念 :就是当前线程所执行的字节码的行号指示器。 JVM的概念模型中,字节码解释器通过改变这个计数器的值来选取下一条字节码指令。 JVM的多线程其实就是通过线程轮流切换并分配处理器执行时间的方式来实现的( 在任何一个确定的时刻内,一个处理器都只会执行一条线程中的指令 )。为了线程切换后能够恢复到正确的执行位置,每条线程都需要有 独立的程序计数器 ,各线程计数器互不影响,独立存储。 所以,程序计数器是 线程私有 的内存区域 如果线程执行一个Java方法,计数器记录的是正在执行的虚拟机字节码指令的地址;如果执行的是Native方法,则计数器的值为空。 Java虚拟机规范中唯一一个 没有规定任何OutOfMemoryError情况 的区域。 二、Java虚拟机栈 线程私有,生命周期与线程相同。 虚拟机描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个 栈帧(Stack Frame) 用于存储局部变量表、操作数栈、动态链接、方法出口等信息。(PS