当前位置:编程学习 > JAVA >>

求高手解决 死锁问题 一个例子

package com.thread;

public class ThreadTest7
{
public static void main(String args[])
{
A a = new A();
Threadadd tadd1 = new Threadadd(a);
Threadadd tadd2 = new Threadadd(a);
Threadsub tsub1 = new Threadsub(a);
Threadsub tsub2 = new Threadsub(a);

tadd1.start();
 tadd2.start();
tsub2.start();
// tsub1.start();
}

}

class A
{
private int i;

public synchronized void increased()
{
// synchronized (this)
// {
// if ((i >= 1) || (i < 0))
if (0 != i)
{
try
{
// System.out.println("when increase value ,beyond our line .."
// + i);
System.out
.println("-->increase method i value is " + i
+ " waiting thread "
+ Thread.currentThread().getName());
this.wait();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
++i;
System.out.println(i+ " "+Thread.currentThread().getName());
this.notify();
}
// }
}

public synchronized void decreased()
{
if (1 == i)
{
--i;
System.out.println(i +" "+Thread.currentThread().getName());
this.notify();
}
else
{
try
{
System.out.println("-->decreased method i value is " + i
+ " waiting thread" + Thread.currentThread().getName());
this.wait();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

class Threadadd extends Thread
{
private A a;

public Threadadd(A a)
{
this.a = a;
}

public void run()
{
while (true)
{
try
{
Thread.sleep((long) Math.random() * 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
a.increased();
}

}
}

class Threadsub extends Thread
{
private A a;

public Threadsub(A a)
{
this.a = a;
}

public void run()
{
while (true)
{
try
{
Thread.sleep((long) Math.random() * 1000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
a.decreased();
}

}
}
有一个规律 当3个线程的时候 如果锁 被2个线程释放2次  那么另外一个线程就 一直不能获得锁 (我猜测的) --------------------编程问答-------------------- 刚才找到根本原因是 waiting pool理的 线程太多了 没有别的线程出来notify 大家都在等着被notify 所以。。 一个临时的解决方案是 : 当waiting pool的个数太多了的时候 就主动发一个notify 。。 不是最好的方案 如果谁有更合适的方案请告诉我牙 。分数照给

package com.thread;

public class ThreadTest7
{
public static void main(String args[])
{
A a = new A();
Threadadd tadd1 = new Threadadd(a);
Threadadd tadd2 = new Threadadd(a);
Threadsub tsub1 = new Threadsub(a);
Threadsub tsub2 = new Threadsub(a);

tadd1.start();
tadd2.start();
tsub2.start();
tsub1.start();
}

}

class A
{
private int i;
private int count; // monitor the thread quatities in the waiting pool.

public synchronized void increased()
{

if (0 != i)
{
try
{
// System.out.println("when increase value ,beyond our line .."
// + i);
System.out
.println("-->increase method i value is " + i
+ " waiting thread "
+ Thread.currentThread().getName());
// Thread.
if ((++count) >= 3)
{
this.notify();
}
this.wait();

}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
++i;
System.out.println(i + " " + Thread.currentThread().getName());
this.notify();
}
// }
}

public synchronized void decreased()
{
if (1 == i)
{
--i;
System.out.println(i + " " + Thread.currentThread().getName());
this.notify();
}
else
{
try
{
System.out.println("-->decreased method i value is " + i
+ " waiting thread" + Thread.currentThread().getName());
if ((++count) >= 3)
{
this.notify();
}
this.wait();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

class Threadadd extends Thread
{
private A a;

public Threadadd(A a)
{
this.a = a;
}

public void run()
{
while (true)
{
try
{
Thread.sleep((long) Math.random() * 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
a.increased();
}

}
}

class Threadsub extends Thread
{
private A a;

public Threadsub(A a)
{
this.a = a;
}

public void run()
{
while (true)
{
try
{
Thread.sleep((long) Math.random() * 1000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
a.decreased();
}

}
} --------------------编程问答-------------------- 去掉你所有的notify,wait就可以了 --------------------编程问答-------------------- 就可以了 --------------------编程问答-------------------- --------------------编程问答-------------------- 楼主,其实我一直不是很明白这个程序是怎么死锁的,调试了N久都没有出现死锁的情况,但一运行就死锁了,表示费解啊 --------------------编程问答--------------------


                 tadd1.start();
//tadd2.start();
tsub2.start();
// tsub1.start();

这样一注释掉就可以了。为什么呢?你有个误区,不是被notify()所唤醒的线程一定是与这个线程执行相反动作的线程。拿你的死锁代码来说:


tadd1.start();
tadd2.start();
tsub2.start();
//  tsub1.start();


有两个执行加法动作的线程,如果tadd1执行完加操作后notify()唤醒了tadd2线程(tsub2一定在wait状态,因为同一时间只能一个线程获得锁),这时候tadd1执行完代码了sleep去了,tadd2执行的代码如下:

this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

然后它也去睡觉了是吧?然后tsub2永远都再wait状态了!这就是为什么你多个notify又可以了一下,不过上述情况依然会出现,还是会死锁。其中一个解决方案是去掉所有的wait,notify。 --------------------编程问答-------------------- 我终于看懂死锁的原因了

我们从最一开始说起

add1运行,然后i变成1
add1再运行,进入wait状态
add2运行,进入wait状态
sub2运行,然后i变成0,add1被notify
sub2运行,进入wait状态
add1运行,然后i变成1,但此时不一定是sub2被notify,如果是add2被notify,那么此后add1和add2都会进入wait状态,然后死锁

出现死锁的原因是因为notify无法指定对象,解决这个现象的方法很简单,你把notify改为notifyAll就行了 --------------------编程问答-------------------- ......死锁个P。。。。最后的那个线程Notify之后wait, 没有其他线程进行唤醒 --------------------编程问答-------------------- 谢谢各位 先说明一下 确实不是死锁... 因为锁一直有 但是没有线程去拿。

当2个线程的时候 就不会出问题

当3个线程的时候 就会出问题。。。 根本原因 我看到的是 当waiting pool里 有3个 线程 都在等着 被notify 这个时候 就可以获得锁了 按照我的思路 100个线程 也不会问题了  

哪位大虾 有更smart的代码么  --------------------编程问答-------------------- 有发现一个问题 当线程数超过 40000的时候 整个电脑会死掉... 我的机器是 4核 内存 4g JDK 7 win7 64

public static void main(String args[])
{
A a = new A();

for (int i = 0; i<10000 ;i++)
{
 (new Threadadd(a)).start();
 (new Threadsub(a)).start();
}
} --------------------编程问答-------------------- 并且我已经把 eclise 的内存加大到512

-startup
plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.100.v20110502
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
512m
--launcher.defaultAction
openFile
-vmargs
-Xms40m
-Xmx384m --------------------编程问答-------------------- 都疯了…… --------------------编程问答-------------------- 你的代码是都在等待唤醒,死锁是互相等待对方持有的资源,又不肯主动放弃已经占有的资源,陷入无限等待的僵局。
这才是死锁:


public class DeadLock
{
    private static final Object lockA = new Object();
    
    private static final Object lockB = new Object();
    
    public static void main(String[] args)
    {
        new Thread()
        {
            @Override
            public void run()
            {
                synchronized (lockA)
                {
                    System.out.println("T1:Get lockA");
                    try
                    {
                        Thread.sleep(1000L); // 等1秒,保证另外一个线程能拿到lockB
                    }
                    catch (InterruptedException e)
                    {
                    }
                    
                    synchronized (lockB)
                    {
                        System.out.println("T1:Get lockB");
                        System.out.println("T1:Get all lock");
                    }
                }
            }
        }.start();
        
        new Thread()
        {
            @Override
            public void run()
            {
                synchronized (lockB)
                {
                    System.out.println("T2:Get lockB");
                    try
                    {
                        Thread.sleep(1000L); // 等1秒,保证另外一个线程能拿到lockA
                    }
                    catch (InterruptedException e)
                    {
                    }
                    
                    synchronized (lockA)
                    {
                        System.out.println("T2:Get lockA");
                        System.out.println("T2:Get all lock");
                    }
                }
            }
        }.start();
    }
    
}
--------------------编程问答-------------------- 补充:使用到了wait,就等于说是主动放弃了已经占有的锁,不符合死锁条件了 --------------------编程问答-------------------- 严重 同意 问题已经解决 notifyall() 就行了 我已经知道了 就是不能回复3次 谢谢了, 但是开线程太多的时候 机器会死 请问有何解释
补充:Java ,  Java SE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,