面试题:
写出一个死锁的实例。
Java发生死锁的根本原因是:
死锁是因为多线程访问共享资源,由于访问的顺序不当所造成的,在申请锁时发生了交叉闭环申请。即线程在获得了锁A并且没有释放的情况下去申请锁B,这时,另一个线程已经获得了锁B,在释放锁B之前又要先获得锁A,因此闭环发生,陷入死锁循环。
实例1:
在MyLock类中定义两个不同的静态锁对象。
package com.deadLock;
class MyLock{
static Object locka = new Object(); //注意此处必须时static,
static Object lockb = new Object(); //不仅能类名访问,也是让不同线程访问共享数据
}
class Lock implements Runnable{
private boolean flag;
public Lock(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
if (flag){
while(true){
deadLockab();
}
}else{
while(true){
deadLockba();
}
}
}
private void deadLockab() {
String name = Thread.currentThread().getName();
synchronized (MyLock.locka){
System.out.println(name+"...lock on "+MyLock.locka);
synchronized (MyLock.lockb){
System.out.println(name+"...lock on "+MyLock.lockb);
}
}
}
private void deadLockba() {
String name = Thread.currentThread().getName();
synchronized (MyLock.lockb){
System.out.println(name+"...lock on "+MyLock.lockb);
synchronized (MyLock.locka){
System.out.println(name+"...lock on "+MyLock.locka);
}
}
}
}
public class DeadLockDemo2 {
public static void main(String[] args) {
Thread t1 = new Thread(new Lock(true));
Thread t2 = new Thread(new Lock(false));
t1.start();
t2.start();
}
}
运行结果(形成死锁):

实例2(无法形成死锁):
在实现Runnable类中定义两个不同的锁,注意两个线程任务不同,所以这两个锁并不是默认静态锁。
package com.deadLock;
class Lock implements Runnable{
private boolean flag;
private Object obj1 = new Object();
private Object obj2 = new Object();
public Lock(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
if (flag){
while(true){
deadLockab();
}
}else{
while(true){
deadLockba();
}
}
}
private void deadLockab() {
String name = Thread.currentThread().getName();
synchronized (obj1){
System.out.println(name+"...lock on "+obj1);
synchronized (obj2){
System.out.println(name+"...lock on "+obj2);
}
}
}
private void deadLockba() {
String name = Thread.currentThread().getName();
synchronized (obj2){
System.out.println(name+"...lock on "+obj2);
synchronized (obj1){
System.out.println(name+"...lock on "+obj1);
}
}
}
}
public class DeadLockDemo2 {
public static void main(String[] args) {
Thread t1 = new Thread(new Lock(true));
Thread t2 = new Thread(new Lock(false));
t1.start();
t2.start();
}
}
运行结果:

实例3(实例2改进,形成死锁):
在实现Runnable类中定义两个不同的锁,并且两个线程任务不同,两个锁必须手动声明为静态锁。
package com.notdeadlock;
class Lock implements Runnable{
private boolean flag;
private static Object obj1 = new Object();
private static Object obj2 = new Object();
public Lock(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
if (flag){
while(true){
deadLockab();
}
}else{
while(true){
deadLockba();
}
}
}
private void deadLockab() {
String name = Thread.currentThread().getName();
synchronized (obj1){
System.out.println(name+"...lock on "+obj1);
synchronized (obj2){
System.out.println(name+"...lock on "+obj2);
}
}
}
private void deadLockba() {
String name = Thread.currentThread().getName();
synchronized (obj2){
System.out.println(name+"...lock on "+obj2);
synchronized (obj1){
System.out.println(name+"...lock on "+obj1);
}
}
}
}
public class NotDeadLock{
public static void main(String[] args) {
Thread t1 = new Thread(new Lock(true));
Thread t2 = new Thread(new Lock(false));
t1.start();
t2.start();
}
}
运行结果:

实例4(形成死锁(2个线程)):
package com.deadlock3;
class Lock implements Runnable{
private Object obj1; //注意此处不能为final/static
private Object obj2;
//如果final就不能在下面构造方法中重新赋值;如果static所有线程共享锁,线程t1,t2都在使用obj2这把锁,无法形成死锁。
public Lock(Object obj1, Object obj2) {
this.obj1 = obj1;
this.obj2 = obj2;
}
@Override
public void run() {
while(true){
deadLock();
}
}
private void deadLock() {
String name = Thread.currentThread().getName();
synchronized (obj1){
System.out.println(name+"...lock on "+obj1);
synchronized (obj2){
System.out.println(name+"...lock on "+obj2);
}
}
}
}
public class DeadLockDemo3 {
public static void main(String[] args) {
Object obj1 = new Object();
Object obj2 = new Object();
Thread t1 = new Thread(new Lock(obj1, obj2));
Thread t2 = new Thread(new Lock(obj2, obj1));
t1.start();
t2.start();
}
}
运行结果:

实例5(形成死锁(3个线程)):
package com.deadlock3;
class Lock implements Runnable{
private Object obj1; //注意此处不能为final/static
private Object obj2;
//如果final就不能在下面构造方法中重新赋值;如果static所有线程共享锁,最后只有两把锁,无法锁住所有线程。
public Lock(Object obj1, Object obj2) {
this.obj1 = obj1;
this.obj2 = obj2;
}
@Override
public void run() {
while(true){
deadLock();
}
}
private void deadLock() {
String name = Thread.currentThread().getName();
synchronized (obj1){
System.out.println(name+"...lock on "+obj1);
synchronized (obj2){
System.out.println(name+"...lock on "+obj2);
}
}
}
}
public class DeadLockDemo3 {
public static void main(String[] args) {
Object obj1 = new Object();
Object obj2 = new Object();
Object obj3 = new Object();
Thread t1 = new Thread(new Lock(obj1, obj2));
Thread t2 = new Thread(new Lock(obj2, obj3));
Thread t3 = new Thread(new Lock(obj3, obj1));
t1.start();
t2.start();
t3.start();
}
}
运行结果:

总结:
推荐使用实例4这种方法形成死锁,代码简单,理解起来也很方便,如果有什么问题,欢迎一起探讨。
本文深入探讨了Java中死锁的成因与实例,通过多个代码示例详细讲解了如何在多线程环境下因不当的锁申请顺序导致死锁现象的发生。
1220

被折叠的 条评论
为什么被折叠?



