今天看啥  ›  专栏  ›  独饮敌敌畏丶_4109

Java学习28 2020-03-15

独饮敌敌畏丶_4109  · 简书  ·  · 2020-03-15 18:07

内容

1.synchronized工作原理
2.synchronized修饰方法
3.一个小面试题(输出结果目前看不懂)
4.类锁
5.死锁

一.synchronized的工作原理

synchronized(this){}
t1线程执行到此处,遇到了synchronized关键字,就会去找 this的对象锁 ,如果找到this对象锁,则进入同步语句块中执行程序,当同步语句块中的代码执行结束之后,t1线程归还this的对象锁。
在t1线程执行同步语句块的过程中,如果t2线程也过来执行这些代码,也遇到synchronized关键字,所以也去找this的对象锁,但是该对象锁 被t1线程持有 ,只能在这等待this对象的归还

二.synchronized修饰方法

使用示例

    public  synchronized void withdraw(double money) {

            double after = balance - money;
            
            //延迟
            try{Thread.sleep(1000);}catch(Exception e) {}
            
            //更新余额
            this.setBalance(after); 
       
        
    }

当synchronized关键字添加到成员方法上的时候,线程拿走的也是this的 对象锁 。但是这种方式不推荐, 不如前面那一种同步的更精细

三.一个小面试题(输出结果目前看不懂)

/*
 * 面试题
 */


public class 测试程序   {                                                                                                             
                                                                                                                        
    public static void main(String[] args) throws InterruptedException  {
   
        //创建mc对象
        MyClass mc = new MyClass();
                
        Processor p = new Processor(mc);
        
        //创建线程t1,t2并命名
        Thread t1 = new Thread(p);
        t1.setName("t1");
        
        Thread t2 = new Thread(p);
        t2.setName("t2");
        
        //启动线程
        t1.start();
        
        //延迟(保证t1先启动,并执行run)
        Thread.sleep(1000);
        
        t2.start();
    }

   
    
}

//创建线程
class Processor implements Runnable
{
    MyClass mc;
    
    Processor(MyClass mc){
        this.mc = mc;
    }
    
    public void run() {
        
        //如果是t1线程,就执行m1
        if(Thread.currentThread().getName().equals("t1"));{
            mc.m1();
        }
        
        //如果是t2线程,就执行m2
        if(Thread.currentThread().getName().equals("t2")) {
            mc.m2();
        }
    }
}
class MyClass{
    
    public synchronized void m1() {
        
        //休眠
        try {
            Thread.sleep(2000);
        }catch(Exception e) {}
        
        System.out.println("m1");
        
        
    }
    
    //m2方法会等m1方法结束,t1,t2共享同一个mc,并且m1和m2方法上都有synchronized
    public synchronized void m2() {
        System.out.println("m2");
    }
}


上面这个程序本应该输出
m1
m2
但是实际上输出了
m1
m1
m2
想了好久也不知道什么原因。

刚才讲的是对象锁,下面讲类锁

四.类锁

1.如何使用

synchronized添加到 静态方法 上,线程执行此方法的时候会找类锁

2.使用示例

public class 测试程序   {                                                                                                             
                                                                                                                        
    public static void main(String[] args) throws InterruptedException  {
   
        Thread t1 = new Thread(new Processor());
        Thread t2 = new Thread(new Processor());
        
        t1.setName("t1");
        t2.setName("t2");
        
        t1.start();
        
        //延迟,保证t1先执行
        Thread.sleep(1000);
        
        t2.start();
        
    }

   
    
}

//创建线程
class Processor implements Runnable
{
    
    
    public void run() {
        
        if("t1".equals(Thread.currentThread().getName())) {
            MyClass.m1();
        }
        if("t2".equals(Thread.currentThread().getName())) {
            MyClass.m2();
        }
        
    }
}
class MyClass{
    
    //synchronized添加到静态方法上,线程执行此方法的时候会找类锁
    public synchronized static void m1() {
        try {
            Thread.sleep(10000);
        }catch(Exception e) {}
        System.out.println("m1...");
        
    }
    
    //不会等m1结束,因为该方法没有被synchronized修饰
    /*public static void m2() {
        System.out.println("m2...");
    }
    */
    //这个m2方法会等m1方法结束之后才执行,因为该方法有synchronized
    //线程执行该代码需要类锁,而类锁只有一个
    public synchronized static void m2() {
        System.out.println("m2...");
    }
}

就会输出
m1...
m2...

五.死锁

public class 测试程序   {                                                                                                             
                                                                                                                        
    public static void main(String[] args) throws InterruptedException  {
   
        Object o1 = new Object();
        Object o2 = new Object();
        
        Thread t1 = new Thread(new T1(o1,o2));
        Thread t2 = new Thread(new T2(o1,o2));
        
        t1.start();
        t2.start();
        
    }

   
    
}

class T1 implements Runnable{
    
    Object o1;
    Object o2;
    
    T1(Object o1,Object o2){
        this.o1 = o1;
        this.o2 = o2;
    }
    
    public void run() {
        synchronized(o1) {
            try{Thread.sleep(1000);}catch(Exception e) {}
            synchronized(o2) {
                
            }
        }
    }
}

class T2 implements Runnable{
    
    Object o1;
    Object o2;
    
    T2(Object o1,Object o2){
        this.o1 = o1;
        this.o2 = o2;
    }
    
    public void run() {
        synchronized(o2) {
            try {
                Thread.sleep(1000);
            }catch(Exception e) {}
            synchronized(o1) {
                
            }
        }
    }
}

这个程序就进入一个 僵持状态
t1刚锁住o1,准备锁o2时,o2已经被t2锁住,此时t2还想锁o1




原文地址:访问原文地址
快照地址: 访问文章快照