java面经查缺补漏之三十九天(继续努力)

1.什么时候用原子操作类,举个例子?

比如一个自增的操作就可以用原则操作类,原子操作类底层用的就是CAS。

2.什么时候用volitile,举个例子?

比如一个boolean的flag,因为它与上个状态无关。

3.手写程序,10个多线程保证 i从0加到10?

可以用原子操作类来实现

import java.util.concurrent.atomic.AtomicInteger;

public class Autoincrease {
    public static void main(String[] args)
    {
        atomicThread matomicThread=new atomicThread();
        for(int i=0;i<10;i++)
        {
            Thread thread=new Thread(matomicThread);
            thread.start();
        }
    }
    public static class atomicThread implements Runnable
    {
        public AtomicInteger i=new AtomicInteger();
        @Override
        public void run() {
            while(true)
            {
                try {
                    Thread.sleep(1000);
                }catch (Exception e)
                {
                    e.printStackTrace();
                }
                System.out.println("线程: " + Thread.currentThread().getName() + "将数据变为: " + i.getAndIncrement());
            }
        }
    }
}

4.如何避免死锁?

主要有三种方式:

参考:https://blog.csdn.net/ls5718/article/details/51896159?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-4&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-4

这篇文章对于死锁的讲解还是不错的

(1)加锁顺序

当多个线程需要相同的一些锁,但是按照不同的顺序加锁,死锁就很容易发生。

比如线程一lockA lockB线程二lockB lockA那么线程一占有A管线程二要B,但此时线程二占有B,它又去管线程一要A,这样就造成了死锁。如果要是都是一样的顺序的话,那么就可以避免死锁了。

按照顺序加锁是一种有效的死锁预防机制。但是,这种方式需要你事先知道所有可能会用到的锁(译者注:并对这些锁做适当的排序),但总有些时候是无法预知的。

(2)加锁时限

超时自动释放锁,就算发生死锁了,也会自动解开。

这种机制存在一个问题,在Java中不能对synchronized同步块设置超时时间。你需要创建一个自定义锁,或使用Java5中java.util.concurrent包下的工具。写一个自定义锁类不复杂,

(3)死锁检测

死锁检测是一个更好的死锁预防机制,它主要是针对那些不可能实现按序加锁并且锁超时也不可行的场景。

当发现死锁的时候,一个可行的做法是释放所有锁,回退,并且等待一段随机的时间后重试。一个更好的方案是给这些线程设置优先级,让一个(或几个)线程回退,剩下的线程就像没发生死锁一样继续保持着它们需要的锁。

5.公平锁与非公平锁的区别?

tryAcquire是公平锁和非公平锁实现的区别,两种类型的锁都是tryAcquire实现的。每一次的tryAcquire都会检查队列中是否仍有前驱的元素,如果仍然有那么继续等待,通过这种方式来保证先来先服务的原则;而非公平锁,首先是检查并设置锁的状态,这种方式会出现即使队列中有等待的线程,但是新的线程仍然会与排队线程中的对头线程竞争(但是排队的线程是先来先服务的),所以新的线程可能会抢占已经在排队的线程的锁,这样就无法保证先来先服务,但是已经等待的线程们是仍然保证先来先服务的。

公平锁能保证:老的线程排队使用锁,新线程仍然排队使用锁。

非公平锁保证:老的线程排队使用锁;但是无法保证新线程抢占已经在排队的线程的锁。

6.synchronized与Lock的区别?

synchronized是一个关键字,可重入,不可判断锁的状态,非公平,自动释放锁。

Lock是一个类,可重入,可判断锁的状态,可公平也可非公平(默认非公平,可构造的时候在ReentrantLock中加入true参数),必须主动释放锁。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章