b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

java多线程死锁_线程 死锁_c++ 线程死锁(2)

电脑杂谈  发布时间:2019-06-22 06:15:06  来源:网络整理

4、什么是乐观锁(Optimistic Locking)?如何实现乐观锁?如何避免ABA问题

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像如果提供类似于write_condition机制的其实都是提供的乐观锁。

5、解释以下名词:重排序,自旋锁,偏向锁,轻量级锁,可重入锁,公平锁,非公平锁,乐观锁,悲观锁

重入锁(ReentrantLock)是一种递归无阻塞的同步机制。重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁。

自旋锁,由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。如何旋转呢?何为自旋锁,就是如果发现锁定了,不是睡眠等待,而是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区。

偏向锁(Biased Locking)是Java6引入的一项多线程优化,它会偏向于第一个访问锁的线程,如果在运行过程中,同步锁只有一个线程访问,不存在多线程争用的情况,则线程是不需要触发同步的,这种情况下,就会给线程加一个偏向锁。 如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会消除它身上的偏向锁,将锁恢复到标准的轻量级锁。

轻量级锁是由偏向所升级来的,偏向锁运行在一个线程进入同步块的情况下,当第二个线程加入锁争用的时候,偏向锁就会升级为轻量级锁。

重入锁(ReentrantLock)是一种递归无阻塞的同步机制,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。 在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁。

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

非公平锁比较粗鲁,上来就直接尝试占有锁,如果尝试失败,就再采用类似公平锁那种方式。

6、什么时候应该使用可重入锁?

场景1:如果已加锁,则不再重复加锁。a、忽略重复加锁。b、用在界面交互时点击执行较长时间请求操作时,防止多次点击导致后台重复执行(忽略重复触发)。以上两种情况多用于进行非重要任务防止重复执行,(如:清除无用临时文件,检查某些资源的可用性,数据备份操作等)

场景2:如果发现该操作已经在执行,则尝试等待一段时间,等待超时则不执行(尝试等待执行)这种其实属于场景2的改进,等待获得锁的操作有一个时间的限制,如果超时则放弃执行。用来防止由于资源处理不当长时间占用导致死锁情况(大家都在等待资源,导致线程队列溢出)。

c++ 线程死锁_线程 死锁_java多线程死锁

场景3:如果发现该操作已经加锁,则等待一个一个加锁(同步执行,类似synchronized)这种比较常见大家也都在用,主要是防止资源使用冲突,保证同一时间内只有一个操作可以使用该资源。但与synchronized的明显区别是性能优势(伴随jvm的优化这个差距在减小)。同时Lock有更灵活的锁定方式,公平锁与不公平锁,而synchronized永远是公平的。这种情况主要用于对资源的争抢(如:文件操作,同步消息发送,有状态的操作等)

1ui线程执行耗时操作 ui线程被阻塞无法响应窗体消息队列中的其他消息。如:(取消正在同步运行的操作,来防止不正常操作长时间占用造成的阻塞)。@synchronized 方法控制对类(一般在ios中用在单例中)的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法锁方能执行,否则所属就会发生线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。

7、简述锁的等级方法锁、对象锁、类锁

@synchronized 方法控制对类(一般在ios中用在单例中)的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法锁方能执行,否则所属就会发生线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。虚拟机会保证一个类的方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的方法,其他线程都需要阻塞等待,直到活动线程执行方法完毕。线程2 bs_rcv_pic_thread使用条件变量阻塞,线程1 ms_snd_pic_thread在recvfrom处阻塞等待udp数据包,所以程1不能给互斥锁上锁,当接收到数据并写完文件后,向条件变量发出信号,以唤醒等待线程2,bs_rcv_pic_thread开始工作。

对象锁(synchronized修饰方法或代码块)当一个对象中有synchronized method或synchronized block的时候调用此对象的同步方法或进入其同步区域时,就必须先获得对象锁。如果此对象的对象锁已被其他调用者占用,则需要等待此锁被释放。(方法锁也是对象锁)。java的所有对象都含有1个互斥锁,这个锁由JVM自动获取和释放。线程进入synchronized方法的时候获取该对象的锁,当然如果已经有线程获取了这个对象的锁,那么当前线程会等待;synchronized方法正常返回或者抛异常而终止,JVM会自动释放对象锁。这里也体现了用synchronized来加锁的1个好处,方法抛异常的时候,锁仍然可以由JVM来自动释放。

3)synchronized 修饰静态方法,锁是该类class对象的锁,该类的所有对象访问该类时都会互斥。答:静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带 static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。静态方法本身就是final的,因为重写只会发生在类实例上,静态方法是和类绑定在一起的,不是对象。

8、Java中活锁和死锁有什么区别?

死锁:是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。死锁发生的四个条件

简单说就是,互斥量的使用流程应该是:线程占用互斥量,然后访问共享资源,最后释放互斥量。一个线程只能在mutex处于激发态的时候访问被保护的资源或代码段,线程可以通过waitforsingelobject来等待mutex,在访问资源完成之后,releasemutex释放mutex,此时mutex处于激发态。而且互斥量能完成对于线程访问互斥资源而异常退出没有释放互斥锁的情况。

2、请求和保持条件:线程T1至少已经保持了一个资源R1占用,但又提出对另一个资源R2请求,而此时,资源R2被其他线程T2占用,于是该线程T1也必须等待,但又对自己保持的资源R1不释放。

3、不剥夺条件:线程已获得的资源,在未使用完之前,不能被其他线程剥夺,只能在使用完以后由自己释放。

环路等待条件:在发生死锁时,必然存在一个进程--资源的环形链。4. 环路等待条件:发生死锁的时候存在的一个 进程-资源 环形等待链。1 定义: 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,形成线程的死锁。

活锁:是指线程1可以使用资源,但它很礼貌,让其他线程先使用资源,线程2也可以使用资源,但它很绅士,也让其他线程先使用资源。这样你让我,我让你,最后两个线程都无法使用资源。

9、如何确保 N 个线程可以访问 N 个资源同时又不导致死锁?

预防死锁,预先破坏产生死锁的四个条件。互斥不可能破坏,所以有如下3种方法:

如果此时还有其他进程请求该资源,则请求资源只能等待,直至占有该资源的进程用毕释放.。2).请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求java多线程死锁,而该资源已经被其他进程占有,此时请求进程被保持,但对自己所获得的资源又保持不放.。2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

2.破坏,不可抢占条件。这种方法代价大,实现复杂

c++ 线程死锁_java多线程死锁_线程 死锁

3.破坏,循坏等待条件。对各进程请求资源的顺序做一个规定,避免相互等待。这种方法对资源的利用率比前两种都高,但是前期要为设备指定序号,新设备加入会有一个问题,其次对用户编程也有限制

10、死锁与饥饿的区别?

相同点:二者都是由于竞争资源而引起的。

不同点:

11、怎么检测一个线程是否拥有锁?

java.lang.Thread中有一个方法叫holdsLock(),它返回true如果当且仅当当前线程拥有某个具体对象的锁

Object o = new Object(); 
@Test 
public void test1() throws Exception { 
    new Thread(new Runnable() { 
        @Override 
        public void run() { 
            synchronized(o) { 
                System.out.println("child thread: holdLock: " +  
                    Thread.holdsLock(o)); 
            } 
        } 
    }).start(); 
    System.out.println("main thread: holdLock: " + Thread.holdsLock(o)); 
    Thread.sleep(2000); 
} 
main thread: holdLock: false
child thread: holdLock: true

12、如何实现分布式锁?

基于实现分布式锁

基于缓存(redis,memcached,tair)实现分布式锁

基于Zookeeper实现分布式锁

可以参考详情《分布式锁的几种实现方式》、《分布式锁的3种方式》

13、有哪些无锁数据结构,他们实现的原理是什么?

java 1.5提供了一种无锁队列(wait-free/lock-free)ConcurrentLinkedQueue,可支持多个生产者多个消费者线程的环境:网上别人自己实现的一种无锁算法队列,原理和jdk官方的ConcurrentLinkedQueue相似:通过volatile关键字来保证数据唯一性(注:java的volatile和c++的volatile关键字是两码事!),但是里面又用到atomic,感觉有点boost::lockfree::queue的风格,估计参考了boost的代码来编写这个java无锁队列。

14、Executors类是什么? Executor和Executors的区别

这个例子的目的是要理解wait和pulse如何保证线程同步的,同时要注意wait(obeject)和wait(object,int)方法的区别,理解它们的区别很关键的一点是要理解同步的对象包含若干引用,其中包括对当前拥有锁的线程的引用、对就绪队列(包含准备获取锁的线程)的引用和对等待队列(包含等待对象状态更改通知的线程)的引用。 } }这个例子的目的是要理解 wait 和 pulse 如何保证线程同步的,同时要注意 wait(obeject) 和 wait(object,int) 方法的区别,理解它们的区别很关键的一点是要理解同步的对象包含若干引用,其中包括对当前拥有锁的线程的引用、对就绪队列(包含准备获取锁的线程)的引用和对等待队列(包含等待对象状态更改通知的线程)的引用。executor框架便是java 5中引入的,其内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架来控制线程的启动、执行和关闭,可以简化并发编程的操作。

java多线程死锁_c++ 线程死锁_线程 死锁

ExecutorExecutorService

Executor 是 Java 线程池的核心接口,用来并发执行提交的任务

ExecutorService 是 Executor 接口的扩展,提供了异步执行和关闭线程池的方法

提供execute()方法用来提交任务

提供submit()方法用来提交任务

execute()方法无返回值

submit()方法返回Future对象java多线程死锁,可用来获取任务执行结果

不能取消任务

可以通过Future.cancel()取消pending中的任务

没有提供和关闭线程池有关的方法

提供了关闭线程池的方法

16、什么是Java线程转储(Thread Dump),如何得到它?

线程转储是一个JVM活动线程的列表,它对于分析系统瓶颈和死锁非常有用。

有很多方法可以获取线程转储——使用Profiler,Kill -3命令,jstack工具等等。我更喜欢jstack工具,因为它容易使用并且是JDK自带的。由于它是一个基于终端的工具,所以我们可以编写一些脚本去定时的产生线程转储以待分析。

17、如何在Java中获取线程堆栈?

Java虚拟机提供了线程转储(thread dump)的后门,通过这个后门可以把线程堆栈打印出来。通常我们将堆栈信息重定向到一个文件中,便于我们分析,由于信息量太大,很可能超出控制台缓冲区的最大行数限制造成信息丢失。这里介绍一个jdk自带的打印线程堆栈的工具,jstack用于打印出给定的Java进程ID或core file或远程调试服务的Java堆栈信息。(Java问题定位之Java线程堆栈分析)

示例:$jstack –l 23561 >> xxx.dump
命令 : $jstack [option] pid >> 文件 

>>表示输出到文件尾部,实际运行中,往往一次dump的信息,还不足以确认问题,建议产生三次dump信息,如果每次dump都指向同一个问题,我们才确定问题的典型性。

18、说出 3 条在 Java 中使用线程的最佳实践

19、【情景开放题】

实际项目中使用多线程举例。你在多线程环境中遇到的常见的问题是什么?你是怎么解决它的?


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-107573-2.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    • 杜欣悦
      杜欣悦

      谁占领钓鱼岛谁实力强

    热点图片
    拼命载入中...