notify 与 nofityall,notify造成死锁实践

Posted silyvin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了notify 与 nofityall,notify造成死锁实践相关的知识,希望对你有一定的参考价值。


package multilock.deadlock;

/**
 * https://www.cnblogs.com/silyvin/p/11747303.html
 * Created by joyce on 2019/10/27.
 */
public class NotifyDeadLock {
    private boolean isSub = true;
    private int count = 0;

    public synchronized void sub() {
        try {
            while (!isSub ) {
                this.wait();
            }
            System. out.println("sub ---- " + count);
            isSub = false ;
            this.notify();   // dead with notify , notifyAll ok
        } catch (Exception e) {
            e.printStackTrace();
        }
        count++;

    }

    public synchronized void main() {
        try {
            while (isSub ) {
                this.wait();
            }
            System. out.println("main (((((((((((( " + count);
            isSub = true ;
            this.notify();  // dead with notify , notifyAll ok
        } catch (Exception e) {
            e.printStackTrace();
        }
        count++;
    }

    public static void main(String[] args) {
        // System.out.println("lock");

        final NotifyDeadLock ot = new NotifyDeadLock();

        for (int j = 0; j < 10; j++) {

            new Thread(new Runnable() {

                public void run() {
                    for (int i = 0; i < 5; i++) {
                        ot.sub();
                    }
                }
            }, "mysub").start();

            new Thread(new Runnable() {

                public void run() {
                    for (int i = 0; i < 5; i++) {
                        ot.main();
                    }
                }
            }, "mymain").start();
        }
    }
}

 

 

输出:

sub ---- 0
main (((((((((((( 1
sub ---- 2
main (((((((((((( 3
sub ---- 4
main (((((((((((( 5
sub ---- 6
main (((((((((((( 7
sub ---- 8
main (((((((((((( 9
sub ---- 10
main (((((((((((( 11
sub ---- 12
main (((((((((((( 13
sub ---- 14
main (((((((((((( 15
sub ---- 16
main (((((((((((( 17
sub ---- 18
main (((((((((((( 19
sub ---- 20
main (((((((((((( 21
sub ---- 22
main (((((((((((( 23
sub ---- 24
main (((((((((((( 25
sub ---- 26
main (((((((((((( 27
sub ---- 28
main (((((((((((( 29
sub ---- 30
main (((((((((((( 31
sub ---- 32
main (((((((((((( 33
sub ---- 34
main (((((((((((( 35
sub ---- 36
main (((((((((((( 37

理论上能打印到99,只到37,使用jstack看一下:

 

技术图片

 

有很多线程wait

技术图片

 

有两种解决方案:

1)改为notifyall,直接改,ok搞定

2)改为reetrantlock,使用两个condition

使用一个condition时,仍然要使用signalall,使用signal会死锁

使用2个condition的代码:

package multilock.deadlock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * https://www.cnblogs.com/silyvin/p/11747303.html
 * Created by joyce on 2019/10/27.
 */
public class NotifyDeadLockRee {
    private boolean isSub = true;
    private int count = 0;

    private ReentrantLock lock = new ReentrantLock();
    private Condition conditionSub = lock.newCondition();
    private Condition conditionMain = lock.newCondition();

    private Condition condition = lock.newCondition(); // dead with signall, signalAll ok


    public void sub() {
        try {
            lock.lock();
            while (!isSub ) {
                conditionSub.await();
            }
            System. out.println("sub ---- " + count);
            isSub = false ;
            conditionMain.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        count++;

    }

    public synchronized void main() {
        try {
            lock.lock();
            while (isSub ) {
                conditionMain.await();
            }
            System. out.println("main (((((((((((( " + count);
            isSub = true ;
            conditionSub.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        count++;
    }

    public static void main(String[] args) {
        // System.out.println("lock");

        final NotifyDeadLockRee ot = new NotifyDeadLockRee();

        for (int j = 0; j < 10; j++) {

            new Thread(new Runnable() {

                public void run() {
                    for (int i = 0; i < 5; i++) {
                        ot.sub();
                    }
                }
            }, "mysub").start();

            new Thread(new Runnable() {

                public void run() {
                    for (int i = 0; i < 5; i++) {
                        ot.main();
                    }
                }
            }, "mymain").start();
        }
    }
}

 

以上是关于notify 与 nofityall,notify造成死锁实践的主要内容,如果未能解决你的问题,请参考以下文章

C++ std::condition_variable notify_one()与notify_all()的作用

java多线程2

JAVA多线程之wait/notify

Java多线程——wait方法和notify方法的详解

Object.wait()与Object.notify()的用法

Object中的wait,notify,notifyAll基本使用(转)