源无极

导航

 

一、静态同步方法synchronized 和 synchronized(this)同步代码块

(一)、静态同步方法synchronize

package com.it.po.thread06;

public class Service1 {
    synchronized public static void printA(){
        try {
            System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printA...");
            Thread.sleep(2000);
            System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printA...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    synchronized public static void printB(){
        try {
            System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printB...");
            Thread.sleep(2000);
            System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printB...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

 

package com.it.po.thread06;
public class MyThread01_1 extends Thread {
    @Override
    public void run() {
        super.run();
        Service1.printA();
    }
}
package com.it.po.thread06;
public class MyThread01_2 extends Thread {
    @Override
    public void run() {
        super.run();
        Service1.printB();
    }
}

 

 

package com.it.po.thread06;
import com.it.po.thread05.Task1;
public class Run01 {
    public static void main(String[] args){
        MyThread01_1 my1 = new MyThread01_1();
        MyThread01_2 my2 = new MyThread01_2();
        my1.setName("A");
        my2.setName("B");
        my1.start();
        my2.start();
    }

}
线程:A 进来了 printA...
线程:A 进来了 printA...
线程:B 进来了 printB...
线程:B 进来了 printB...

 

 总结: synchronized 加到带static的方法上是给类加锁,和synchronized  加到非static的方法上(是给对象加锁没有什么区别。

 (二)、静态同步方法synchronize 和非static 的synchronize 方法

 

package com.it.po.thread06;

public class Service2 {
    synchronized public static void printA(){
        try {
            System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printA...");
            Thread.sleep(2000);
            System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printA...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    synchronized public static void printB(){
        try {
            System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printB...");
            Thread.sleep(2000);
            System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printB...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    synchronized  public  void printC(){
        try {
            System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printB...");
            Thread.sleep(2000);
            System.out.println("线程:"+Thread.currentThread().getName()+" 进来了 printB...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

 

 

package com.it.po.thread06;
public class MyThread02_1 extends Thread {
    @Override
    public void run() {
        super.run();
        Service1.printA();
    }
}

 

 

package com.it.po.thread06;
public class MyThread02_2 extends Thread {
    @Override
    public void run() {
        super.run();
        Service1.printA();
    }
}

 

 

package com.it.po.thread06;
public class MyThread02_3 extends Thread {
    @Override
    public void run() {
        super.run();
        Service2 service2 = new Service2();
        service2.printC();

    }
}

 

 

package com.it.po.thread06;
public class Run02 {
    public static void main(String[] args){
        MyThread02_1 my1 = new MyThread02_1();
        MyThread02_2 my2 = new MyThread02_2();
        MyThread02_3 my3 = new MyThread02_3();
        my1.setName("A");
        my2.setName("B");
        my3.setName("C");
        my3.start();
        my1.start();
        my2.start();
    }

}

 

 

线程:A 进来了 printA...
线程:C 进来了 printB...
线程:A 进来了 printA...
线程:B 进来了 printA...
线程:C 进来了 printB...
线程:B 进来了 printA...

 

 区别:锁类和锁对象的。

 

 (三)、静态方法同步代码块的特点

package com.it.po.thread06;

public class Service3 {
     public static void printA(){
         synchronized(Service2.class) {
             try {
                 System.out.println("线程:" + Thread.currentThread().getName() + " 进来了 printA...");
                 Thread.sleep(2000);
                 System.out.println("线程:" + Thread.currentThread().getName() + " 进来了 printA...");
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         }
    }

    synchronized public static void printB(){
        synchronized(Service2.class) {
            try {
                System.out.println("线程:" + Thread.currentThread().getName() + " 进来了 printB...");
                Thread.sleep(2000);
                System.out.println("线程:" + Thread.currentThread().getName() + " 进来了 printB...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    synchronized  public  void printC(){
        synchronized(Service2.class) {
            try {
                System.out.println("线程:" + Thread.currentThread().getName() + " 进来了 printB...");
                Thread.sleep(2000);
                System.out.println("线程:" + Thread.currentThread().getName() + " 进来了 printB...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

 

 

package com.it.po.thread06;
public class MyThread03_1 extends Thread {
    private Service3 service3;
    public MyThread03_1(Service3 service3) {
        this.service3 = service3;
    }
    @Override
    public void run() {
        super.run();
        service3.printA();
    }
}

 

 

package com.it.po.thread06;
public class MyThread03_2 extends Thread {
    private Service3 service3;
    public MyThread03_2(Service3 service3) {
        this.service3 = service3;
    }

    @Override
    public void run() {
        super.run();
        service3.printB();
    }
}

 

 

package com.it.po.thread06;
public class MyThread03_3 extends Thread {
    private Service3 service3;
    public MyThread03_3(Service3 service3) {
        this.service3 = service3;
    }
    @Override
    public void run() {
        super.run();
        service3.printC();
    }
}

 

 

package com.it.po.thread06;

public class Run03 {
    public static void main(String[] args){
        Service3 service3 = new Service3();
        MyThread03_1 my1 = new MyThread03_1(service3);
        MyThread03_2 my2 = new MyThread03_2(service3);
        MyThread03_3 my3 = new MyThread03_3(service3);
        my1.setName("A");
        my2.setName("B");
        my3.setName("C");
        my3.start();
        my1.start();
        my2.start();
    }

}
线程:A 进来了 printA...
线程:A 进来了 printA...
线程:B 进来了 printB...
线程:B 进来了 printB...
线程:C 进来了 printB...
线程:C 进来了 printB...

 

修改如下

package com.it.po.thread06;
public class MyThread03_1 extends Thread {
    private Service3 service3;

    public MyThread03_1(Service3 service3) {
        this.service3 = service3;
    }
    @Override
    public void run() {
        super.run();
       // service3.printA();
        Service3.printA();
    }
}

 

 

线程:A 进来了 printA...
线程:A 进来了 printA...
线程:C 进来了 printB...
线程:C 进来了 printB...
线程:B 进来了 printB...
线程:B 进来了 printB...

 

注意:锁定的是类。 

 二、同步方法无限等待与解决

 

package com.it.po.thread06;

public class Service4 {
  synchronized public void methodA(){
     System.out.println("线程 "+Thread.currentThread().getName()+" 进入methodA 。。");
     boolean po=true;
     while (po){
     }
      System.out.println("线程 "+Thread.currentThread().getName()+" 走出methodA 。。");
  }

     synchronized public void methodB(){
        System.out.println("线程 "+Thread.currentThread().getName()+" 进入methodB 。。");
        System.out.println("线程 "+Thread.currentThread().getName()+" 走出methodB 。。");
    }

}

 

package com.it.po.thread06;
public class MyThread04_1 extends Thread {
    private Service4 service4;
    public MyThread04_1(Service4 service4) {
        this.service4 = service4;
    }
    @Override
    public void run() {
        super.run();
        service4.methodA();
    }
}

 

package com.it.po.thread06;
public class MyThread04_2 extends Thread {
    private Service4 service4;
    public MyThread04_2(Service4 service4) {
        this.service4 = service4;
    }
    @Override
    public void run() {
        super.run();
        service4.methodB();
    }
}

 

package com.it.po.thread06;
public class Run04 {
    public static void main(String[] args){
        Service4 service4 = new Service4();
        MyThread04_1 my1 = new MyThread04_1(service4);
        MyThread04_2 my2 = new MyThread04_2(service4);
        my1.setName("A");
        my2.setName("B");
        my1.start();
        my2.start();
    }

}

 

 

 

 解决无限等锁办法:

package com.it.po.thread06;

import com.sun.org.apache.bcel.internal.generic.NEW;

public class Service4 {
    Object object1=new Object();
    Object object2=new Object();
   public void methodA(){
       synchronized(object1) {
           System.out.println("线程 " + Thread.currentThread().getName() + " 进入methodA 。。");
           boolean po = true;
           while (po) {
           }
           System.out.println("线程 " + Thread.currentThread().getName() + " 走出methodA 。。");
       }
  }

      public void methodB(){
          synchronized(object2) {
              System.out.println("线程 " + Thread.currentThread().getName() + " 进入methodB 。。");
              System.out.println("线程 " + Thread.currentThread().getName() + " 走出methodB 。。");
          }
    }

}

 

三、多线程的死锁

多线程的死锁是非常经典的问题,不同的线程在等待不可能释放的锁,导致假死状态。

package com.it.po.thread06;

public class DealThread implements Runnable {
 public String username;
 public Object lock1=new Object();
 public Object lock2=new Object();
 public void setUsername(String username){
     this.username=username;
 }
    @Override
    public void run() {
        if("a".equals(username)){
            synchronized (lock1) {
                try {
                    System.out.println("a1: username= "+username);
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock2) {
                    System.out.println("a2: username= "+username);
                }
            }

        }
        if("b".equals(username)){
            synchronized (lock2) {
                try {
                    System.out.println("b1: username= "+username);
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock1) {
                    System.out.println("b2: username= "+username);
                }
            }

        }

    }
}

 

package com.it.po.thread06;
import com.sun.org.apache.bcel.internal.generic.NEW;
public class RunDeal {
    public static void main(String[] args) throws InterruptedException {
        DealThread t1 = new DealThread();
        t1.setUsername("a");
        Thread t2 = new Thread(t1);
        t2.start();
        Thread.sleep(50);
        t1.setUsername("b");
        Thread t3 = new Thread(t1);
        t3.start();

    }

}

 

 

 

 

 1.在jdkd的bin文件下打开命令: 输入jps

 

2.记住程序 RunDeal 的id值 97404  继续输入命令:jstack+ id

 

 

 

 

 确实发生死锁。

注意:实际开发中,没有例子中 synchronized 的嵌套,也是会发生死锁的,死锁与嵌套不嵌套没有关系。

 

 

 

 

posted on 2019-11-17 00:41  源无极  阅读(248)  评论(0)    收藏  举报