java并发篇

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

一、java如何开启线程?怎么保证线程安全?

  1. 线程和进程的区别:进程是操作系统进行资源分配的最小单元、线程是操作系统进行任务分配的最小单元,线程属于进程
  2. 如何开启线程:常用的两种方式 继承Thread类,重写run方法、实现Runnable接口,实现run方法,两种实现方法是由于java的单继承多实现的机制,避免继承了Thread就不能继承其他的类,没有扩展性,所以常用的实现Runnable;另外还有一种方法是 实现Callable接口,实现call方法,这个方式是由返回值,如果需要放回线程中的数据时,可以使用此种方法,通过FutureTask创建一个线程,获取到线程返回值;最后就是通过线程池来创建线程(线程池后面单独介绍)。
  3. 如何保证线程安全?
    核心思想就是 加锁 :JVM提供的锁,也就是Synchronized关键字、还有就是JDK提供各种锁Lock

二、Volatile和Synchronized有什么区别?Volatile能不能保证线程安全?DCL(Double Check Lock)单例为什么要加Volatile?

  1. Volatile和Synchronized有什么区别
    volatile的使用可查看 java并发篇之volatile关键字
    Synchronized关键字,用来加锁。Volatile只是保证变量的线程可见性。通常适用于一个变量在一个线程写,多个线程读的场景。
  2. Volatile能不能保证线程安全?
    不能,Volatile关键字只能保存线程可见性,不能保证原子性
  3. DCL(Double Check Lock)单例为什么要加Volatile?
    首先看以下代码
public class SingDemo {

    private static SingDemo singDemo = new SingDemo();
    // 私有化
    private SingDemo(){};

    public static SingDemo getInstance(){
        return singDemo;
    }

}

这是一个简单的单例模式,在项目启动时就将对象实例化,但是有时想要在用的时候在加载对象,可以将代码改成

public class SingDemo {

    private static SingDemo singDemo;
    // 私有化
    private SingDemo(){};

    public static SingDemo getInstance(){
        if(null == singDemo){
            singDemo = new SingDemo();
        }
        return singDemo;
    }

}

初始化时不new对象,而是在用的时候判断后初始化对象,但是这样的代码就会有线程不安全的问题,同时两个线程访问时,可能会创建两次,这个时候可以加锁

public class SingDemo {

    private static SingDemo singDemo;
    // 私有化
    private SingDemo(){};

    public static SingDemo getInstance(){
        if(null == singDemo){
            synchronized (SingDemo.class){
                if(null == singDemo){
                    singDemo = new SingDemo();
                }
            }
        }
        return singDemo;
    }
}

当线程1进来判断为空,继续进入实例化,这时不管来多少线程都会被锁住,当线程1创建成功之后,后续线程解锁后会再次进行一次判断,这样就不会重复创建了,这种就叫做DCL(Double Check Lock)双重检查。
回归正题,Volatile在DCL中防止高并发的情况下防止指令重排造成的指令重排。
如下图,创建一个 Integer i = 8 这样一个包装类,CPU在底层会分为3步执行,
1、在堆内存中分配控件,不进行初始化
2、对象初始化,设值为8
3、栈建立指针与堆内存的关系
在单线程中不会存在问题,如果在多线程高并发的情况下,可能会出现顺序错误,就叫指令重排,这是就需要Volatile,保证指令的正确顺序
在这里插入图片描述

三、java线程锁机制是怎样的?偏向锁、轻量级锁、重量级锁有什么区别?

public class JolDemo {
    public static void main(String[] args) {
        Object o = new Object();
        System.out.println(ClassLayout.parseInstance(o).toPrintable());
        synchronized (o){
            System.out.println(ClassLayout.parseInstance(o).toPrintable());
        }
    }
}

上面代码可以将未加锁和加锁之后的对象在JVM内存对象中的布局给打印出来
在这里插入图片描述
java 的锁只是在对象的Markword中记录一个锁状态,无锁、偏向锁、轻量级锁、重量级锁对应不同的锁状态
在这里插入图片描述

四、有A,B,C三个线程,如何保证三个线程同时执行?如何在并发情况下保证三个线程依次执行?如何保证三个线程有序交错进行?

原文地址 CountDownLatch、CylicBarrier、Semaphore的区别

面试题是结合B站楼兰老师的面试课总结而来,可直接看楼兰老师视频 楼兰老师面试课程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值