synchronized产生的死锁

死锁是两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁。死锁通常发生在多个线程同时但以不同的顺序请求同一组锁的时候。

例如,如果线程1锁住了A,然后尝试对B进行加锁,同时线程2已经锁住了B,接着尝试对A进行加锁,这时死锁就发生了。线程1永远得不到B,线程2也永远得不到A,并且它们永远也不会知道发生了这样的事情。为了得到彼此的对象(A和B),它们将永远阻塞下去。这种情况就是一个死锁。

该情况如下:

Thread 1  locks A, waits for B
Thread 2  locks B, waits for A
package com.smart.concurrency.chapter1;

/**
 * @Description  死锁的例子
 * @author gaowenming
 */
public class DeadLock {

    /** A锁 */
    private static String A = "A";

    /** B锁 */
    private static String B = "B";

    public static void main(String[] args) {
        new DeadLock().deadLock();
    }

    public void deadLock() {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (A) {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (B) {
                        System.out.println("thread1...");
                    }
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (B) {
                    synchronized (A) {
                        System.out.println("thread2...");
                    }
                }
            }
        });

        t1.start();
        t2.start();

    }

}

上面的2个线程的执行过程如下:

线程1开始执行,拿到了锁A,休眠2秒,线程2执行,先拿到了锁B,在请求拿锁A,而由于此时线程1已经占用了锁A,所以就等待线程1释放锁A,休眠结束后,线程1继续往下执行,请求拿到锁B,而锁B被线程2占用,从而形成了死锁。

java中,解决死锁一般有如下方法:

1)尽量使用tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),设置超时时间,超时可以退出防止死锁。 
2)尽量使用java.util.concurrent(jdk 1.5以上)包的并发类代替手写控制并发,比较常用的是ConcurrentHashMap、ConcurrentLinkedQueue、AtomicBoolean等等,实际应用中java.util.concurrent.atomic十分有用,简单方便且效率比使用Lock更高 
3)尽量降低锁的使用粒度,尽量不要几个功能用同一把锁 
4)尽量减少同步的代码块

时间: 2024-10-05 15:06:55

synchronized产生的死锁的相关文章

Java多线程总结之由synchronized说开去(转)

这几天不断添加新内容,给个大概的提纲吧,方面朋友们阅读,各部分是用分割线隔开了的: synchronized与wait()/notify() JMM与synchronized ThreadLocal与synchronized ReentrantLock与synchronized 最重要一条: synchronized是针对对象的隐式锁使用的,注意是对象! 举个小例子,该例子没有任何业务含义,只是为了说明synchronized的基本用法: Java代码   Class MyClass(){ sy

Java多线程总结之由synchronized说开去

最重要一条: synchronized是针对对象的隐式锁使用的,注意是对象! 举个小例子,该例子没有任何业务含义,只是为了说明synchronized的基本用法: Java代码   Class MyClass(){ synchronized void myFunction(){ //do something } } public static void main(){ MyClass myClass = new MyClass(); myClass.myFunction(); } 好了,就这么简

java学习第22天(关于java中的锁LOCK及多线程的面试题)

在JDK5后,java提供一种更加方便的安全机制,不使用synchronized,针对线程的锁定操作和释放操作使用Lock锁.更加清晰明了.举例: Lock lock=new ReentrantLock(); lock.lock 需要加锁的代码 lock.unlock  为什么说lock更为安全呢?因为synchronized可能会造成死锁现象,具体关于死锁现象可以参考操作系统,就不再多说. 总结下在线程中的主要几个问题 首先是 多线程有几种实现方式 应该上是有三种,第一种继承Thread类,第

java多线程实用操作

线程控制基本方法方    法                             功    能 isAlive()                     判断线程是否还"活"着,即当前run线程是否还未终止. getPriority()               获得线程的优先级数值 setPriority()               设置线程的优先级数值 Thread.sleep()           将当前线程睡眠指定毫秒数 join()               

Java多线程(一):

1. 实现线程的两种方式TraditionalThread 继承Thread类,实现implements Runable接口 2. Timer/TimerTask定时器使用(53) TraditionalTimerTest 题目:写一个Timer实现输出一个字符串,第一次间隔2s,第二次间隔4s,第三次间隔2s,交替进行.两种实现(使用一个Timer,使用两个Timer). 注意:匿名内部类中不能定义static变量. 更好的开源框架学习:quartz 3. 线程互斥技术(synchronize

JAVA多线程及补充

进程 运行中的应用程序叫进程,每个进程运行时,都有自已的地址空间(内存空间)如IE浏览器在任务管器中可以看到操作系统都是支持多进程的 线程 线程是轻量级的进程,是进程中一个负责程序执行的控制单元线程没有独立的地址空间(内存空间)线程是由进程创建的(寄生在进程中)一个进程可以拥有多个线程,至少一个线程线程有几种状态(新建new,就绪Runnable,运行Running,阻塞Blocked,死亡Dead)开启多个线程是为了同时运行多部分代码,每个线程都有自已的运行的内容,这个内容可以称线程要执行的任

Java并发编程从入门到精通 - 第3章:Thread安全

Java内存模型与多线程: 线程不安全与线程安全: 线程安全问题阐述:  多条语句操作多个线程共享的资源时,一个线程只执行了部分语句,还没执行完,另一个线程又进来操作共享数据(执行语句),导致共享数据最终结果出现误差:所以就是看一个线程能否每次在没有其他线程进入的情况下操作完包含共享资源的语句块,如果能就没有安全问题,不能就有安全问题: 如何模拟多线程的安全问题:  用Thread.sleep()方法模拟: 放在哪:放在多线程操作共享数据的语句块之间(使正在运行的线程休息一会,让其他线程执行,就

多线程2-synchronize

一.线程安全问题 多线程操作各自线程创建的资源的时候,不存在线程安全问题.但多线程操作同一个资源的时候就会出现线程安全问题.下例为两个线程操作同一个name资源时发生的问题. class TestSyn { public static void main(String[] args) throws Exception { Resource resource = new Resource(); new Thread() { @Override public void run() { while (

java多线程编程从入门到卓越(超详细总结)

导读:java多线程编程不太熟?或是听说过?或是想复习一下?找不到好的文章?别担心我给你们又安利一波,文章内容很全,并且考虑到很多开发中遇到的问题和解决方案.循环渐进,通俗易懂,文章较长,建议收藏再看! 往期精彩放送:一文搞定Java的输入输出流等常见流 一文搞定Java集合类,你还在为Java集合类而烦恼吗? 文章目录 1.多线程的概念 2.多线程并发 3.多线程程序设计 继承Thread类创建线程 新建类实现Runnable接口创建线程 改进(匿名内部类方式) 获取线程的名字和当前线程对象