美文网首页
java-多线程

java-多线程

作者: 隔壁丨王大爷 | 来源:发表于2018-09-14 10:10 被阅读25次

    介绍一下Syncronized锁。如果用这个关键字修饰一个静态方法,锁住了什么?如果修饰成员方法,锁住了什么?

    修饰静态方法、修饰成员变量:相当于全局锁,相当于锁住了整个类。

    synchronized(this)以及非static的synchronized方法(至于static synchronized方法请往下看),只能防止多个线程同时执行同一个对象的同步代码段

    介绍一下volatile

    保证可见性,有序性

    当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。

    在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比sychronized关键字更轻量级的同步机制。

    而声明变量是 volatile 的,JVM 保证了每次读变量都从内存中读

    lock(防止指令重排序)

    在执行程序时为了提高性能,编译器和处理器通常会对指令做重排序:

    编译器重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序;

    处理器重排序。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序;

    多线程中的i++线程安全吗?为什么?

    局部变量中安全,全局变量不安全。

    i++不是原子性操作,相当于int tp1 = i; int tp2 = tp1+1; i = tp2; 

    如何线程安全的实现一个计数器?

    使用AtomicInteger 等原子类。

    给i++加锁

    线程同步有哪几种方式

    1.同步方法

    2.同步代码块  

    3.使用特殊域变量(volatile)实现线程同步

    4.使用重入锁实现线程同步 

    5.使用局部变量实现线程同步 (使用ThreadLocal管理变量)

    6.wait与notify

    7.使用原子变量实现线程同步

    concurrenthashmap有啥优势,1.7,1.8区别

    http://www.importnew.com/23610.html

    AQS(AbstractQueuedSynchronized)

    Java并发之AQS详解 - CodesGeek - 博客园

    CAS(Compare And Swap )

    如果V值等于E值,则将V的值设为N。若V值和E值不同,则说明已经有其他线程做了更新,则当前线程什么都不做。

    通俗的理解就是CAS操作需要我们提供一个期望值,当期望值与当前线程的变量值相同时,说明还没线程修改该值,当前线程可以进行修改,也就是执行CAS操作,但如果期望值与当前线程不符,则说明该值已被其他线程修改,此时不执行更新操作,但可以选择重新读取该变量再尝试再次修改该变量,也可以放弃操作

    ABA

    比如说一个线程one从内存位置V中取出A,这时候另一个线程two也从内存中取出A,并且two进行了一些操作变成了B,然后two又将V位置的数据变成A,这时候线程one进行CAS操作发现内存中仍然是A,然后one操作成功。尽管线程one的CAS操作成功,但是不代表这个过程就是没有问题的。如果链表的头在变化了两次后恢复了原值,但是不代表链表就没有变化。因此前面提到的原子操作。

    各种乐观锁的实现中通常都会用版本戳version来对记录或对象标记,避免并发操作带来的问题。

    线程安全的Map都有啥,Collections.synchronizedmap(),ConcurrentHashMap,Hashtable 底层实现

    线程池运行流程,参数,策略

    线程池相关笔记,线程池的实现?四种线程池?重要参数及原理?任务拒接策略有哪几种? - CSDN博客

    synchronized,偏向锁,轻量级锁,重量级锁,锁膨胀机制

    Synchronized的原理及自旋锁,偏向锁,轻量级锁,重量级锁的区别 - CSDN博客

    wait方法底层原理 join,notify,notifyall

    多线程(二):详细描述wait、notify/notifyAll、join及底层实现 - CSDN博客

    线程池原理

    理解线程池的原理 - CSDN博客

    讲一下非公平锁和公平锁在reetrantlock里的实现。

    FairSync 公平锁 

    公平锁就是每个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程线程是等待队列的第一个,就占有锁,否则就会加入到等待队列中,以后会按照FIFO的规则从队列中获取,

    讲一下synchronized,可重入怎么实现

    Java中一个线程在通过synchronized获取到一个对象的对象锁后会阻塞试图获取该对象锁的其他线程,但不会阻塞当前线程,也就是说synchronized代码块对当前线程来说是可重入的

    多线程实现方法

    继承Thread类创建线程类,重写run方法,run方法就是代表线程需要完成的任务,调用线程对象的start()来启动该线程,线程类已经继承了Thread类,所以不能再继承其他父类。   

    实现Runnable接口创建线程类,定义Runnable实现类,重写run方法   

    实现Callable接口,重写call()方法,call()作为线程的执行体,具有返回值   

    线程池,使用线程池产生线程对象java.util.concurrent.ExecutorService、java.util.concurrent.Executors;

    Synchronized和lock区别

    Lock提供了synchronized关键字所不具备的主要特性有:

    尝试非阻塞地获取锁boolean tryLock():当前线程尝试获取锁,如果这一时刻没有被其他线程获取到,则成功获取并持有锁       

    能被中断地获取锁void lockInterruptibly():当获取到锁的线程被中断时,中断异常抛出同时会释放锁       

    超时获取锁boolean trylock(long time, TimeUnit unit):在指定截止时间之前获取锁,如果在截止时间仍旧无法获取锁,则返回     

    synchronized是JVM提供的加锁,悲观锁;lock是Java语言实现的,而且是乐观锁。   

    ReentrantLock是基于AQS实现的,由于AQS是基于FIFO队列的实现

    Java中都有什么锁

    重量级锁、显式锁、并发容器、并发同步器、CAS、volatile、AQS等

    可重入锁的设计思路是什么

    可重入公平锁获取流程

    在获取锁的时候,如果当前线程之前已经获取到了锁,就会把state加1,在释放锁的时候会先减1,这样就保证了同一个锁可以被同一个线程获取多次,而不会出现死锁的情况。这就是ReentrantLock的可重入性。

    对于非公平锁而言,调用lock方法后,会先尝试抢占锁,在各种判断的时候会先忽略等待队列,如果锁可用,就会直接抢占使用。

    乐观锁和悲观锁

    悲观锁:假定会发生并发冲突,则屏蔽一切可能违反数据完整性的操作

    乐观锁:假定不会发生并发冲突,只在数据提交时检查是否违反了数据完整性(不能解决脏读问题)

    juc包内有哪些类

    CountDownLatch 同步计数器,主要用于线程间的控制,但计数无法被重置,如果需要重置计数,请考虑使用 CyclicBarrier 。

    线程池新任务到达时会先使用空闲线程还是加入阻塞队列

    Java并发包里面的CountdownLatch怎么使用

    这个类是一个同步计数器,主要用于线程间的控制,当CountDownLatch的count计数>0时,await()会造成阻塞,直到count变为0,await()结束阻塞,使用countDown()会让count减1。CountDownLatch的构造函数可以设置count值,当count=1时,它的作用类似于wait()和notify()的作用。如果我想让其他线程执行完指定程序,其他所有程序都执行结束后我再执行,这时可以用CountDownLatch,但计数无法被重置,如果需要重置计数,请考虑使用 CyclicBarrier 。

    volatile和synchronized区别

    volatile是变量修饰符,其修饰的变量具有可见性,Java的做法是将该变量的操作放在寄存器或者CPU缓存上进行,之后才会同步到主存,使用volatile修饰符的变量是直接读写主存,volatile不保证原子性,同时volatile禁止指令重排   

    synchronized作用于一段代码或者方法,保证可见性,又保证原子性,可见性是synchronized或者Lock能保证通一个时刻只有一个线程获取锁然后执行不同代码,并且在释放锁之前会对变量的修改刷新到主存中去,原子性是指要么不执行,要执行就执行到底

    一般线程和守护线程的区别

    java中的线程分为两种:守护线程(Daemon)和用户线程(User)。

    任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bool on);true则把该线程设置为守护线程,反之则为用户线程。Thread.setDaemon()必须在Thread.start()之前调用,否则运行时会抛出异常。

    唯一的区别是判断虚拟机(JVM)何时离开,Daemon是为其他线程提供服务,如果全部的User Thread已经撤离,Daemon 没有可服务的线程,JVM撤离。也可以理解为守护线程是JVM自动创建的线程(但不一定),用户线程是程序创建的线程;比如JVM的垃圾回收线程是一个守护线程,当所有线程已经撤离,不再产生垃圾,守护线程自然就没事可干了,当垃圾回收线程是Java虚拟机上仅剩的线程时,Java虚拟机会自动离开。

    相关文章

      网友评论

          本文标题:java-多线程

          本文链接:https://www.haomeiwen.com/subject/ozhkgftx.html