首页 > Java > java教程 > Java 中的死锁

Java 中的死锁

WBOY
发布: 2024-08-30 15:40:06
原创
922 人浏览过

在Java中,死锁是多线程的一种情况,线程1等待线程2获得对象锁,线程2等待线程1获得对象锁。这里,线程1和线程2都互相等待释放锁。 Java 中的多线程程序可能会导致死锁,因为关键字synchronized 会在等待与所提到的对象链接的监视器或锁时阻塞执行线程。让我们在以下部分中看到死锁的工作原理和示例。

开始您的免费软件开发课程

网络开发、编程语言、软件测试及其他

死锁是如何工作的?

正如所讨论的,同步方法可以锁定代码的特定部分。对于Java中的每个对象,都会有一个锁,同步是一种锁定函数或代码块的技术,以确保一次只有1个线程可以访问该函数或代码块。

当特定线程需要执行同步函数时,它首先尝试获取锁。同时,如果另一个线程已经收到锁,则第一个线程将等待,直到线程 2 释放锁。尽管同步可以防止数据不一致的问题,但仍然存在同步问题。

假设有 2 个线程,“线程 1”和“线程 2”。线程 1 已获得对象 1 的锁定,线程 2 已获得对象 2 的锁定。线程 1 执行方法 1,想要获得对象 2 的锁定。但是,线程 2 已经获得对象 2 的锁定。

此外,线程2还需要获得对象1的锁;但是,线程 1 拥有对象 1 上的锁。此时,线程 1 和线程 2 这两个线程都无法完成其执行,只能永远等待该锁。这种情况称为死锁。

Java 中的死锁示例

下面给出了提到的示例:

示例#1

实现死锁的Java程序。

代码:

public class DeadLockExample {
//main method
public static void main(String[] args) throws InterruptedException {
//create three objects 1, 2 and 3
Object o1 = new Object();
Object o2 = new Object();
Object o3 = new Object();
//create three threads 1, 2 and 3
Thread th1 = new Thread(new SynchronizationThread(o1, o2), "thread 1");
Thread th2 = new Thread(new SynchronizationThread(o2, o3), "thread 2");
Thread th3 = new Thread(new SynchronizationThread(o3, o1), "thread 3");
//start thread 1
th1.start();
//thread sleeps for 5000 seconds
Thread.sleep(5000);
//start thread 2
th2.start();
//thread sleeps for 5000 seconds
Thread.sleep(5000);
//start thread 3
th3.start();
}
}
class SynchronizationThread implements Runnable
{
private Object o1;
private Object o2;
public SynchronizationThread(Object o1, Object o2){
this.o1=o1;
this.o2=o2;
}
//function run
@Override
public void run() {
//store the name of the thread
String nm = Thread.currentThread().getName();
System.out.println( nm + " attaining lock on "+ o1 ) ;
synchronized (o1)
{
System.out.println( nm + " attained lock on "+ o1 ) ;
work();
System.out.println( nm + " attaining lock on "+ o2 ) ;
synchronized (o2) {
System.out.println( nm + " attained lock on "+ o2 );
work();
}
System.out.println( nm + " released lock on "+ o2 ) ;
}
System.out.println( nm + " released lock on "+ o1 ) ;
System.out.println( nm + " completed execution.") ;
}
//function work
private void work() {
try {
//thread sleeps
Thread.sleep(30000);
}
//catch the exception
catch (InterruptedException exc)
{
exc.printStackTrace();
}
}
}
登录后复制

输出:

Java 中的死锁

示例#2

在这个程序中,3个正在运行的线程共享一个资源,并且它们以获取对象1上的锁的方式运行,但是当它尝试获取对象2上的锁时,它会进入等待状态。为了防止死锁,可以将代码重写如下。

代码:

public class DeadLockExample {
public static void main(String[] args) throws InterruptedException {
Object o1 = new Object();
Object o2 = new Object();
Object o3 = new Object();
Thread th1 = new Thread(new SynchronizationThread(o1, o2), "thread 1");
Thread th2 = new Thread(new SynchronizationThread(o2, o3), "thread 2");
Thread th3 = new Thread(new SynchronizationThread(o3, o1), "thread 3");
//start thread 1, 2 and 3
th1.start();
//thread sleeps for 5000 seconds
Thread.sleep(5000);
th2.start();
//thread sleeps for 5000 seconds
Thread.sleep(5000);
th3.start();
}
}
class SynchronizationThread implements Runnable{
private Object o1;
private Object o2;
public SynchronizationThread(Object o1, Object o2){
this.o1=o1;
this.o2=o2;
}
//function run
@Override
public void run() {
//store the name of the thread
String nm = Thread.currentThread().getName();
System.out.println( nm + " attaining lock on "+ o1 ) ;
synchronized (o1)
{
System.out.println( nm + " attained lock on "+ o1 ) ;
work();
}
System.out.println( nm + " released lock on "+ o1 ) ;
System.out.println( nm + " acquiring lock on " + o2 );
synchronized (o2) {
System.out.println( nm + " attained lock on "+ o2 );
work();
}
System.out.println( nm + " released lock on "+ o2 ) ;
System.out.println( nm + " released lock on "+ o1 ) ;
System.out.println( nm + " completed execution.") ;
}
//function work
private void work() {
try {
//thread sleeps
Thread.sleep(30000);
}
//catch the exception
catch (InterruptedException exc)
{
exc.printStackTrace();
}
}
}
登录后复制

输出:

Java 中的死锁

如何避免 Java 中的死锁?

以下是有助于避免死锁情况的指南。

1.避免嵌套锁

嵌套锁是导致死锁的常见原因之一。如果另一资源已持有一个资源,请勿锁定该资源以避免死锁。如果用户仅使用 1 个对象,则不可能导致死锁。

2.只锁定需要的内容

人们建议仅锁定必要的资源。但是,即使不需要,某些用户也可能会尝试锁定资源。

3.避免无限期等待

如果两个线程借助线程连接无限期地等待对方完成,就会发生死锁。如果线程需要等待其他线程完成,最好使用具有等待线程完成的最大时间的 join。

以上是Java 中的死锁的详细内容。更多信息请关注PHP中文网其他相关文章!

相关标签:
来源:php
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板