一段多线程锁机制的代码,看完你会提高不少。

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/caonima0001112/article/details/50482129

最近看到一段很有意思的代码,先贴出来。

/** 
     *  
     *      sleep(); 休眠,不会丢失任何监视器的所有权 
     *       wait(); 等待,释放对监视器的所有权  
     *     notice(); Wakes up a single thread that is waiting on this object's monitor 
     *  notifyAll(); Wakes up all threads that are waiting on this object's monitor. 
     *  synchronized: 加锁同步,实际上就是并行执行串行化 
     * @author Administrator 
     * 
     */  
    public class Test {  
        public static void main(String[] args) {  
            MyClass1 myClass = new MyClass1();  
            new MyThread(myClass).start();  
            new MyThread1(myClass).start();  
        }  
    }  
    class MyClass1 {  
        public synchronized void m1() {  
            System.out.println("m1-1");  
            try {  
             // wait():当前线程等待,直到另一个线程调用notify()或者notifyAll();  
            // 执行wait()方法后释放对监视器(myClass.m1())的所有权,也就是释放锁  
                this.wait(); // 暂停改当前线程,并且会释放锁  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
            System.out.println("m1-2");  
            try {  
                Thread.sleep(1000); // m1和m2同时暂停1秒钟  
                System.out.println("m1-3");  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
            System.out.println("m1-4");  
            m2();  
        }  
        public synchronized void m2() {  
            System.out.println("m2-1");  
            // 唤醒m1,但是并不释放锁synchronized  
        // Wakes up all threads that are waiting on this object's monitor   
            this.notifyAll();
            System.out.println("m2-2");  
            try {  
             // 当前正在执行的线程休眠,线程不丢失任何监视器的所有权,也就是不会释放锁  
                Thread.sleep(1000);  
                System.out.println("m2-3");  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
            System.out.println("m2-4");  
            m1();  
        }  
    }  
    class MyThread extends Thread {  
        private MyClass1 myClass;  
        public MyThread(MyClass1 myClass){  
            this.myClass = myClass;  
        }  
        @Override  
        public void run() {  
            myClass.m1();  
        }  
    }  
    class MyThread1 extends Thread {  
        private MyClass1 myClass;  
        public MyThread1(MyClass1 myClass){  
            this.myClass = myClass;  
        }  
        @Override  
        public void run() {  
            try { // 暂停10毫秒是为了让m1先执行wait  
                Thread.sleep(10);  
            } catch (InterruptedException e1) {  
                e1.printStackTrace();  
            }  
            myClass.m2();  
        }  
    }  

线程基础不好的相信已经看晕了,没关系,实践是检验真理的唯一标准,下面我们看在JDK1.6下面的运行结果:

[test] 2011-03-19 09:25:25 [Thread-0] :m1-1
[test] 2011-03-19 09:25:25 [Thread-1] :m2-1
[test] 2011-03-19 09:25:25 [Thread-1] :m2-2
[test] 2011-03-19 09:25:26 [Thread-1] :m2-3
[test] 2011-03-19 09:25:26 [Thread-1] :m2-4
[test] 2011-03-19 09:25:26 [Thread-1] :m1-1
[test] 2011-03-19 09:25:26 [Thread-0] :m1-2
[test] 2011-03-19 09:25:27 [Thread-0] :m1-3
[test] 2011-03-19 09:25:27 [Thread-0] :m1-4
[test] 2011-03-19 09:25:27 [Thread-0] :m2-1
[test] 2011-03-19 09:25:27 [Thread-0] :m2-2
[test] 2011-03-19 09:25:28 [Thread-0] :m2-3
[test] 2011-03-19 09:25:28 [Thread-0] :m2-4
[test] 2011-03-19 09:25:28 [Thread-0] :m1-1
[test] 2011-03-19 09:25:28 [Thread-1] :m1-2
[test] 2011-03-19 09:25:29 [Thread-1] :m1-3
[test] 2011-03-19 09:25:29 [Thread-1] :m1-4
[test] 2011-03-19 09:25:29 [Thread-1] :m2-1
[test] 2011-03-19 09:25:29 [Thread-1] :m2-2
[test] 2011-03-19 09:25:30 [Thread-1] :m2-3
[test] 2011-03-19 09:25:30 [Thread-1] :m2-4
[test] 2011-03-19 09:25:30 [Thread-1] :m1-1
[test] 2011-03-19 09:25:30 [Thread-0] :m1-2
[test] 2011-03-19 09:25:31 [Thread-0] :m1-3
[test] 2011-03-19 09:25:31 [Thread-0] :m1-4
[test] 2011-03-19 09:25:31 [Thread-0] :m2-1
[test] 2011-03-19 09:25:31 [Thread-0] :m2-2
[test] 2011-03-19 09:25:32 [Thread-0] :m2-3
[test] 2011-03-19 09:25:32 [Thread-0] :m2-4
[test] 2011-03-19 09:25:32 [Thread-0] :m1-1
[test] 2011-03-19 09:25:32 [Thread-1] :m1-2
[test] 2011-03-19 09:25:33 [Thread-1] :m1-3
[test] 2011-03-19 09:25:33 [Thread-1] :m1-4
[test] 2011-03-19 09:25:33 [Thread-1] :m2-1
[test] 2011-03-19 09:25:33 [Thread-1] :m2-2
[test] 2011-03-19 09:25:34 [Thread-1] :m2-3
[test] 2011-03-19 09:25:34 [Thread-1] :m2-4
[test] 2011-03-19 09:25:34 [Thread-1] :m1-1
[test] 2011-03-19 09:25:34 [Thread-0] :m1-2
[test] 2011-03-19 09:25:35 [Thread-0] :m1-3
[test] 2011-03-19 09:25:35 [Thread-0] :m1-4
[test] 2011-03-19 09:25:35 [Thread-0] :m2-1
[test] 2011-03-19 09:25:35 [Thread-0] :m2-2
[test] 2011-03-19 09:25:36 [Thread-0] :m2-3
[test] 2011-03-19 09:25:36 [Thread-0] :m2-4
[test] 2011-03-19 09:25:36 [Thread-0] :m1-1
[test] 2011-03-19 09:25:36 [Thread-1] :m1-2
[test] 2011-03-19 09:25:37 [Thread-1] :m1-3
[test] 2011-03-19 09:25:37 [Thread-1] :m1-4
[test] 2011-03-19 09:25:37 [Thread-1] :m2-1
[test] 2011-03-19 09:25:37 [Thread-1] :m2-2
[test] 2011-03-19 09:25:38 [Thread-1] :m2-3
[test] 2011-03-19 09:25:38 [Thread-1] :m2-4
[test] 2011-03-19 09:25:38 [Thread-1] :m1-1
[test] 2011-03-19 09:25:38 [Thread-0] :m1-2
[test] 2011-03-19 09:25:39 [Thread-0] :m1-3
[test] 2011-03-19 09:25:39 [Thread-0] :m1-4
[test] 2011-03-19 09:25:39 [Thread-0] :m2-1
[test] 2011-03-19 09:25:39 [Thread-0] :m2-2
[test] 2011-03-19 09:25:40 [Thread-0] :m2-3
[test] 2011-03-19 09:25:40 [Thread-0] :m2-4
[test] 2011-03-19 09:25:40 [Thread-0] :m1-1
[test] 2011-03-19 09:25:40 [Thread-1] :m1-2 

下面开始分析我们的代码:

  1. 首先Thread-0是我们的MyThread线程,Thread-1是MyThread1线程。
  2. 程序启动Thread-0,m1方法被调用打印m1-1
  3. wait方法使线程对象放弃对象锁,等待被唤醒Thread-0线程被挂起,等待其它线程唤醒,Thread-1线程执行,m2 方法被调用;
  4. 打印m2-1,notifyAll()唤醒所有的线程,Thread-0被唤醒,但notifyall()不放开对象锁,Thread-1继续执行,打印m2-2;
  5. sleep方法使当前线程停止执行,放弃cpu时间片,让其他线程执行,但sleep方法不会使当前线程放弃锁,故m2 挂起, 1秒过后,打印m2-3,m2-4;
  6. 由于m2 持有MyClass1的锁,m2中的m1 方法可以继续执行,打印m1-1,但是由于没有释放锁,此时的线程还是在Thread-1中;
  7. 之后Thread-1遇到wait 方法使线程放弃对象锁,等待被唤醒,Thread-1被挂起,由于m2中的notifyall()已经唤醒Thread-0,所以Thread-0 开始继续执行,打印m1-2;
  8. 之后sleep方法使线程Thread-0 挂起,但不会放弃对象锁,1秒过后,继续打印m1-3,m1-4;
  9. 之后继续调用m2方法,注意此时线程仍是Thread-0,依次打印m2-1,不释放锁线程不变继续打印m2-2,m2-3,m2-4,调用m1方法,打印m1-1,这时遇到wait()Thread-0被挂起,Thread-1执行,紧接上次Thread-1停止的地方m1-1之后,打印m1-2。注意是Thread-1线程下。
  10. 重复以上过程,直至线程StackOverflowError退出。

多线程学习之路:站在大牛的肩膀上

http://blog.csdn.net/fenglibing/article/details/6278883 多线程各个方法介绍。

http://blog.psjay.com/posts/summary-of-java-concurrency-one-thread-fundation/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io Java并发总结(一):线程基础

http://blog.psjay.com/posts/summary-of-java-concurrency-two-synchronized-and-atomicity/ Java并发总结(二):同步与原子性

http://blog.psjay.com/posts/summary-of-java-concurrency-three-interrupt/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io Java并发总结(三):中断线程

http://blog.psjay.com/posts/summary-of-java-concurrency-four-collaboration/ Java并发总结(四):线程的协作

猜你喜欢

转载自blog.csdn.net/caonima0001112/article/details/50482129