多线程8锁


多线程8锁

题目

在AA线程执行的代码下面有一行Thread.sleep(100);
保证了这个题目中的AA能先抢到执行权

  • 1 标准访问,先打印短信还是邮件
    短信
  • 2 停4秒在短信方法内,先打印短信还是邮件
    短信

一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了,其它的线程都只能等待。换句话说,某一个时刻内,只能有唯一 一个线程(当前对象this)去访问这些synchronized方法锁,被锁定后,其它的线程都不能进入到当前对象的其它的synchronized方法
      相当于是锁的对象


  • 3 新增普通的hello方法,是先打短信还是hello
    Hello

加个普通方法后发现和同步锁无关。只会限制该对象的有锁方法,没有加锁的方法可以正常访问


  • 4 现在有两部手机,先打印短信还是邮件
    邮件

两个手机,相当于不是同一把锁了。手机1号的线程访问的是第一把锁,但是手机2号的线程访问的是第二把锁。二者互不干扰,对于BB来说,它之前并没有线程占用它的锁,所以可以直接拿到发邮件方法,而不用等待4S。


  • 5 两个静态同步方法,1部手机,先打印短信还是邮件
    短信
  • 6 两个静态同步方法,2部手机,先打印短信还是邮件
    短信

静态同步方法锁的是Class对象,不管你有一个手机 还是两个手机,只要有一个线程进入了,那么剩下的必须老老实实的等待。
例如:
对于普通同步方法相当于锁的是每一个厕所的隔间门,假如你有两个对象,一个进了一个厕所隔间,那么另一个进另外一个厕所隔间就行。
但是静态同步方法就相当是一个人进了厕所,直接给厕所大门关了,不管你有几个人,必须等他给你开大门才可以继续。


  • 7 1个静态同步方法,1个普通同步方法,1部手机,先打印短信还是邮件
    邮件
  • 8 1个静态同步方法,1个普通同步方法,2部手机,先打印短信还是邮件
    邮件

所有的静态同步方法用的是同一把锁——类对象本身,普通同步方法用的锁是锁的当前的对象,这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同步方法之间,只要它们同一个类的实例对象!


synchronized实现同步的基础:Java中的每一个对象都可以作为锁。
具体表现为以下3种形式:
对于普通同步方法,锁是当前实例对象。
对于静态同步方法,锁是当前类的Class对象。
对于同步方法块,锁是Synchonized括号里配置的对象

代码

package cduck.cn;

import java.util.concurrent.TimeUnit;

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

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

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

/**
 * * @Description: 8锁 *
 * 1 标准访问,先打印短信还是邮件
 * 2 停4秒在短信方法内,先打印短信还是邮件
 * 3 新增普通的hello方法,是先打短信还是hello
 * 4 现在有两部手机,先打印短信还是邮件
 * 5 两个静态同步方法,1部手机,先打印短信还是邮件
 * 6 两个静态同步方法,2部手机,先打印短信还是邮件
 * 7 1个静态同步方法,1个普通同步方法,1部手机,先打印短信还是邮件
 *8 1个静态同步方法,1个普通同步方法,2部手机,先打印短信还是邮件
 *  * --------------------------------- *
 */
public class Lock_8 {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();
        Phone phone2 = new Phone();
        new Thread(() -> {
            try {
                phone.sendSMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "AA").start();
        Thread.sleep(100);
        new Thread(() -> {
            try {
                phone.sendEmail();
                phone.getHello();
                phone2.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "BB").start();
    }
}

文章作者: fFee-ops
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 fFee-ops !
评论
  目录