synchronized

java并发面试题(七)

白昼怎懂夜的黑 提交于 2020-02-28 03:29:19
重写run()方法时可以对外抛出异常么? 答:不行,因为被重写的run()方法自身就没有抛出异常的定义,所以run()方法里要是有异常,在内部就要try/catch了。 线程可以连续调用两次start方法么? 答:可参考本篇博客 线程连续两次调用start()方法 。 简述锁的等级方法锁、对象锁、类锁? 答:首先要了解每个对象都有一个可以用来实现同步的锁,称为内置锁。方法锁和对象锁指的其实是同一个东西,只是synchronized关键字使用的地方不同而已,都是作用于实例对象,所以如果是相同类的不同实例,它们的锁也是不同的。而类也是一个特殊的对象,类锁就是作用于类上的锁,比如静态同步方法的锁就是类锁,这时候再多的实例,只要它们归属的类是相同的,那抢的就是同一把锁。 多线程的价值? 答:首先可以充分利用多核CPU的优势,其次可以防止阻塞,完全可以在一个任务阻塞时,先做其他的任务,然后等第一个任务返回后再做统合,最后使用多线程可以对任务进行拆解,把一个大任务拆分成几个小任务运行,当然,能否成功拆解还是要看具体的业务逻辑。 锁机制有什么用? 答:多线程情况下,保证信息的同步,结果的正确。 请说出你所知的线程同步的方法? 答: wait() : 使一个线程处于等待状态,并且释放所持有的对象的锁。 sleep() : 使一个正在运行的线程处于睡眠状态(睡眠可以理解成睡到一定时间线程自己就会醒)

Java synchronized 关键字详解

旧巷老猫 提交于 2020-02-28 02:16:38
Java synchronized 关键字详解 前置技能点 进程和线程的概念 线程创建方式 线程的状态状态转换 线程安全的概念 synchronized 关键字的几种用法 修饰非静态成员方法 synchronized public void sync(){ } 修饰静态成员方法 synchronized public static void sync(){ } 类锁代码块 synchronized (类.class){ } 对象锁代码块 synchronized (this|对象){ } synchronized 修饰非静态方法时可以看做是锁 this 对象,修饰静态方法时可以看做是锁方法所在的类。 synchronized 关键字的根本机制 各个线程想要访问被 synchronized 修饰的代码块,就要取得 synchronized 声明的锁。如果两个线程的目标是同一个锁,就会出现阻塞的现象,所以两个线程不能同时访问同一个锁下的代码,保证了多线程在执行时最终结果不会出错。这与共享变量是否为静态无关。 几个例子 对象锁 public class ThreadDemo extends Thread { @Override public synchronized void run() { for (int i = 0; i < 10000; i++) { Main.i++; }

Java面试题-Java中的锁

杀马特。学长 韩版系。学妹 提交于 2020-02-28 00:18:45
1. 如何实现乐观锁(CAS)?如何避免ABA问题? 答:1)读取内存值的方式实现了乐观锁(比如:SVN系统),方法:第一,比较内存值和期望值;第二,替换内存值为要替换值。 2)带参数版本来避免aba问题,在读取和替换的时候进行判定版本是否一致 2. 读写锁可以用于什么应用场景? 答: 读写锁可以用于 “多读少写” 的场景,读写锁支持多个读操作并发执行,写操作只能由一个线程来操作 ReadWriteLock对向数据结构相对不频繁地写入,但是有多个任务要经常读取这个数据结构的这类情况进行了优化。ReadWriteLock使得你可以同事有多个读取者,只要它们都不试图写入即可。如果写锁已经被其他任务持有,那么任何读取者都不能访问,直至这个写锁被释放为止。 ReadWriteLock 对程序心性能的提高受制于如下几个因素也还有其他等等的因素。 1)数据被读取的频率与被修改的频率相比较的结果。 2)读取和写入的时间 3)有多少线程竞争 4)是否在多处理机器上运行 3. 什么时候应该使用可重入锁? 答:重入锁指的是在某一个线程中可以多次获得同一把锁,在线程中多次操作有锁的方法。 4. 什么场景下可以使用volatile替换synchronized? 答: 只需要保证共享资源的可见性的时候可以使用volatile替代,synchronized保证可操作的原子性一致性和可见性

Java并发高频面试题

雨燕双飞 提交于 2020-02-27 21:24:15
前面整理了Java基础、Mysql、Spring的高频面试题,今天为大家带来Java并发方面的高频面试题,因为并发知识不管在学习、面试还是工作过程中都非常非常重要,看完本文,相信绝对能助你一臂之力。 1、线程和进程有什么区别? 线程是进程的子集,一个进程可以有很多线程。每个进程都有自己的内存空间,可执行代码和唯一进程标识符(PID)。 每条线程并行执行不同的任务。不同的进程使用不同的内存空间(线程自己的堆栈),而所有的线程共享一片相同的内存空间(进程主内存)。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。 2、实现多线程的方式有哪些? 继承Thread类:Java单继承,不推荐; 实现Runnable接口:Thread类也是继承Runnable接口,推荐; 实现Callable接口:实现Callable接口,配合FutureTask使用,有返回值; 使用线程池:复用,节约资源; 更多方式可以参考我的文章使用Java Executor框架实现多线程 3、用Runnable还是Thread? 这个问题是上题的后续,大家都知道我们可以通过继承Thread类或者调用Runnable接口来实现线程,问题是,那个方法更好呢?什么情况下使用它?这个问题很容易回答,如果你知道Java不支持类的多重继承,但允许你调用多个接口。所以如果你要继承其他类

线程类Thread sleep 与wait的区别

南楼画角 提交于 2020-02-27 15:15:37
1、sleep是Thread类的方法,wait是Object类的方法 2、sleep不会释放对象锁,wait会释放锁 3、sleep不需要与synchronized一起使用,wait需要 4、sleep不需要唤醒,wait需要 import java.util.stream.Stream; public class DifferenceOfWaitAndSleep { private final static Object LOCK = new Object(); public static void main(String[] args) { Stream.of("T1", "T2").forEach(name -> new Thread(name) { @Override public void run() { m2(); } }.start() ); } public static void m1() { synchronized (LOCK) { try { System.out.println("The Thread " + Thread.currentThread().getName() + " enter."); Thread.sleep(20000); } catch (InterruptedException e) { e.printStackTrace(); }

AtomicReference与volatile的区别

穿精又带淫゛_ 提交于 2020-02-27 08:53:29
首先volatile是java中关键字用于修饰变量,AtomicReference是并发包java.util.concurrent.atomic下的类。 首先volatile作用,当一个变量被定义为volatile之后,看做“程度较轻的 synchronized”,具备两个特性: 1.保证此变量对所有线程的可见性(当一条线程修改这个变量值时,新值其他线程立即得知) 2.禁止指令重新排序 注意volatile修饰变量不能保证在并发条件下是线程安全的,因为java里面的运算并非原子操作。 volatile说明 java.util.concurrent.atomic工具包,支持在单个变量上解除锁的线程安全编程。其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当某个线程进入方法,执行其中的指令时,不会被其他线程打断,而别的线程就像自旋锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择一个另一个线程进入,这只是一种逻辑上的理解。 AtomicReference说明 Java 理论与实践: 正确使用 Volatile 变量 Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized ”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少

JAVA多线程

半世苍凉 提交于 2020-02-27 08:50:52
JAVA多线程 1.进程与线程介绍  进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)。  线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)。  进程的栈内存和堆内存都是独立的,而线程的栈内存是独立的,堆内存是共享的。 2.实现多线程的两种方式 继承Thread类,重写该类的run()方法。 实现Runnable接口,并重写该接口的run()方法,该run()方法同样是线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象。 区别: 实现Runnable接口比继承Thread类所具有的优势: 1):适合多个相同的程序代码的线程去处理同一个资源 2):可以避免java中的单继承的限制 3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立 4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类 3.线程池   Jdk1.5后提供了Executor为我们管理Thread对象,从而简化了并发编程。Executor允许你管理异步任务的执行,而无须显式地管理线程的生命周期且这是jdk1

架构师内功心法,经典高频面试的单例模式详解

回眸只為那壹抹淺笑 提交于 2020-02-27 08:15:51
一、单例模式应用场景 单例模式(Single Pattern)是指 确保一个类在任何情况下绝对只是一个实例,并提供一个全局的访问点。 单例模式在现实生活中的应用也很广泛。例如国家总统、公司CEO、部门经理等。在java标准中,ServletContext、ServletContextConfig等;在Spring框架中ApplicationCotext;数据库对应的连接池也都是单例形势的。 二、单例模式分类 2.1 饿汉式单例 饿汉式单例是在类加载的时候就立即初始化了,并且创建了单例对象。绝对的线程安全,在线程还没出现以前就实例化了,不可能存在访问安全问题。 优点:没有加任何的锁,执行效率高,在用户体验上,比懒汉式更好。 缺点:类加载的时候就初始化了,不管用与不用都占空间,浪费了内存,有可能占着茅坑不拉屎。 Spring中的IOC容器ApplicationContext 本身就是典型的饿汉式单例。案例代码: public class HungrySingleton { /** * 先静态后动态 * 先属性后方法 * 先上后下 */ private static final HungrySingleton hungrySingleton = new HungrySingleton(); private HungrySingleton() { } public static

聊聊artemis的DiscoveryGroup

心不动则不痛 提交于 2020-02-27 01:51:53
序 本文主要研究一下artemis的DiscoveryGroup DiscoveryGroup activemq-artemis-2.11.0/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/cluster/DiscoveryGroup.java public final class DiscoveryGroup implements ActiveMQComponent { private static final Logger logger = Logger.getLogger(DiscoveryGroup.class); private final List<DiscoveryListener> listeners = new ArrayList<>(); private final String name; private Thread thread; private boolean received; private final Object waitLock = new Object(); private final Map<String, DiscoveryEntry> connectors = new ConcurrentHashMap<>(); private final long

synchronized使用和实现原理

一世执手 提交于 2020-02-27 00:21:14
一 synchronized 使用 1. 对象锁: a. 同步代码块synchronized(this),synchronized(类实例对象),锁是小括号中的实例对象 b. 同步非静态方法synchronized method,锁是当前对象的实例对象 2. 类锁: a. 同步代码块Synchronized(类.class),锁是小括号中类的对象 b. 同步静态方法Synchronized static method,锁是当前对象的类对象 3. 例子 二synchronized实现原理 Java对象头+ Monitor 2.1 对象的内存布局 =对象头+实例数据+对齐填充 2.1.1 对象头分类 i. markWord 默认存储对象的hashCode,分代年龄,锁类型,锁标志位等信息 ii. Class metadata Address 类型指针指向对象的类元数据,JVM通过这个指针确定该对象是哪个类的数据 2.1.2 markword 对象需要存储的运行时数据很多,其实已经超过了32位、64为bitmap结构所能记录的限度,但是对象头是与对象自身定义的数据无关的额外存储成本,考虑到虚拟机的空间效率,markword被设计成一个非固定的数据结构以便在极小的空间存储尽量多的信息,它会根据对象的状态复用自己的存储空间。例如,在32位的hotSpot虚拟机中,举个例子,如下图第一行