多线程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();
}
}