Title

JUC多线程并发——8锁

8锁:
1.标准访问,请问先打印邮件还是短信?
2.邮件方法暂停4秒钟,请问先打印邮件还是短信?
3.新增一个普通方法hello(),请问先打印邮件还是hello?
4.两部手机,请问先打印邮件还是短信?
5.两个静态同步方法,同一部手机,请问先打印邮件还是短信?
6.两个静态同步方法,2部手机,请问先打印邮件还是两部手机,请问先打印邮件还是短信?
7.1个普通同步方法,1个静态同步方法,1部手机,请问先打印邮件还是短信?
8.1个普通同步方法,1个静态同步方法,2部手机,请问先打印邮件还是短信?


1.标准访问,请问先打印邮件还是短信?

class Phone{
    public synchronized void sendEmail() throws Exception {
        System.out.println("----sendEmail");
    }

    public synchronized void sendMS() throws Exception {
        System.out.println("----sendMS");
    }
}

public class Lock8 {
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();

        new Thread(()->{
            try {
                phone.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();

        new Thread(()->{
            try {
                phone.sendMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

这里的结果并不是按顺序得到的,而是两个线程互相抢占锁资源。

只是线程A运气更好,CPU先调度A线程,A先抢到了锁对象,从而调用同步方法sendEmail()

在A释放锁对象后,B才能占用锁对象,调用同步方法sendMS()

如果要的效果是:线程A先执行,线程B后执行。可以在线程A后面添加Thread.sleep(1000);TimeUnit.SECONDS.sleep(1);为方便演示后面的锁都添加延时。

这样就是固定顺序,先线程A后线程B,出现上面的结果是理所当然的。

 

下面这个例子,就是演示了两个线程互相抢占锁资源。

class Phone{
    public synchronized void sendEmail() throws Exception {
        System.out.println("----sendEmail");
    }

    public synchronized void sendMS() throws Exception {
        System.out.println("----sendMS");
    }
}

public class Lock8 {
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();

        new Thread(()->{
            try {
                for (int i = 0; i < 10; i++) {
                    phone.sendEmail();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();

        new Thread(()->{
            try {
                for (int i = 0; i < 10; i++) {
                    phone.sendMS();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}


2.邮件方法暂停4秒钟,请问先打印邮件还是短信?

class Phone{
    public synchronized void sendEmail() throws Exception {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("----sendEmail");
    }

    public synchronized void sendMS() throws Exception {
        System.out.println("----sendMS");
    }
}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();

        new Thread(()->{
            try {
                    phone.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(200);

        new Thread(()->{
            try {
                    phone.sendMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

很明显,A线程先占用锁对象,过4秒才会释放锁对象,B线程阻塞;4秒后B线程再占用锁对象。


3.新增一个普通方法hello(),请问先打印邮件还是hello?

class Phone{
    public synchronized void sendEmail() throws Exception {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("----sendEmail");
    }

    public synchronized void sendMS() throws Exception {
        System.out.println("----sendMS");
    }

    public void hello(){
        System.out.println("----hello");
    }
}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();

        new Thread(()->{
            try {
                    phone.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(200);

        new Thread(()->{
            try {
                    phone.hello();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

普通方法不参与锁对象的抢占,他执行他的,我执行我的。

线程A先调用sendEmail()进入sleep,虽然sleep过程不释放锁资源,但是线程B调用的hello()不是同步方法,不会等待锁资源释放,直接执行。


4.两部手机,请问先打印邮件还是短信?

class Phone{
    public synchronized void sendEmail() throws Exception {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("----sendEmail");
    }

    public synchronized void sendMS() throws Exception {
        System.out.println("----sendMS");
    }
}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();

        new Thread(()->{
            try {
                    phone1.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(200);

        new Thread(()->{
            try {
                    phone2.sendMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

此时,由于是分别使用两个锁对象调用方法,执行过程中两个线程互不干扰,线程B不会等待锁对象释放,直接执行phone2对象的sendMS()方法。


5.两个静态同步方法,同一部手机,请问先打印邮件还是短信?

class Phone{
    public static synchronized void sendEmail() throws Exception {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("----sendEmail");
    }

    public static synchronized void sendMS() throws Exception {
        System.out.println("----sendMS");
    }
}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();

        new Thread(()->{
            try {
                    phone.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(200);

        new Thread(()->{
            try {
                    phone.sendMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

这个应该很好理解,主要看6

 

6.两个静态同步方法,2部手机,请问先打印邮件还是两部手机,请问先打印邮件还是短信?

class Phone{
    public static synchronized void sendEmail() throws Exception {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("----sendEmail");
    }

    public static synchronized void sendMS() throws Exception {
        System.out.println("----sendMS");
    }
}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();

        new Thread(()->{
            try {
                    phone1.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(200);

        new Thread(()->{
            try {
                    phone2.sendMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

static作用于方法上,说明这个方法属于类。可以这么调用:Phone.sendEmail();

而static sychronized相当于锁了类模板,其他线程再调用类模板中的静态同步方法必须等待之前的锁释放。


7.1个普通同步方法,1个静态同步方法,1部手机,请问先打印邮件还是短信?

class Phone{
    public static synchronized void sendEmail() throws Exception {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("----sendEmail");
    }

    public synchronized void sendMS() throws Exception {
        System.out.println("----sendMS");
    }
}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();

        new Thread(()->{
            try {
                    phone.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(200);

        new Thread(()->{
            try {
                    phone.sendMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

由于一个锁的是Person.class类模板,一个锁的是person对象,虽然是一部手机,但是不是同一个锁,他执行他的,我执行我的。


8.1个普通同步方法,1个静态同步方法,2部手机,请问先打印邮件还是短信?

class Phone{
    public synchronized void sendEmail() throws Exception {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("----sendEmail");
    }

    public static synchronized void sendMS() throws Exception {
        System.out.println("----sendMS");
    }
}

public class Lock8 {
    public static void main(String[] args) throws Exception {
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();

        new Thread(()->{
            try {
                    phone1.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(200);

        new Thread(()->{
            try {
                    phone2.sendMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

phone1.sendEmail();普通同步方法 锁的是person1对象

phone2.sendMS();静态同步方法 锁的是Person.class类模板

两部手机,锁的东西也不一样,自然是互不影响。


以上均为个人学习过程中记录的所思所想,代码和文章亲自手打。

如有错误,烦请指出。

posted @ 2022-04-13 16:26  clutch-man  阅读(71)  评论(0)    收藏  举报