8锁问题
问题:Phone 有两个方法,发送邮件和发送短信,每个方法都打印一句话,现在通过不同的方式对方法进行操作,回答出打印的先后顺序
1、标准访问,两线程中间睡眠 2 毫秒,先打印邮件还是短信?
class Phone {
public synchronized void sendEmail() {
System.out.println("send email...");
}
public synchronized void sendSMS() {
System.out.println("send SMS...");
}
}
public class Lock8 {
public static void main(String[] args) throws Exception {
Phone phone = new Phone();
new Thread(() -> phone.sendEmail(), "A").start();
TimeUnit.MILLISECONDS.sleep(200);
new Thread(() -> phone.sendSMS(), "A").start();
}
}
答案:
send email…
send SMS…
分析:main线程创建A线程后,睡眠200ms,此时,A线程进入就绪状态,而B线程还没有创建,200ms已经足够A线程获取cpu的时间片。
2、在 sendEmail() 方法中睡眠 4 秒,先打印邮件还是短信?
class Phone {
public synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("send email...");
}
public synchronized void sendSMS() {
System.out.println("send SMS...");
}
}
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();
TimeUnit.MILLISECONDS.sleep(200);
new Thread(() -> phone.sendSMS(), "A").start();
}
}
答案:
send email…
send SMS…
分析:一个对象内如果有多个synchronized 方法,同一时间点,只会有一个线程去调用synchronized 方法,synchronized 锁的是当前对象this,被锁定后,其他线程都不能进入到当前对象的其他synchronized 方法,所以A线程一定比B线程先执行,而sleep()方法睡眠不释放锁,B只能等A睡醒后释放锁在执行。
3、新增一个普通的hello方法,先打印邮件还是短信?
class Phone {
public synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("send email...");
}
public synchronized void sendSMS() {
System.out.println("send SMS...");
}
public void hello() {
System.out.println("send SMS...");
}
}
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();
TimeUnit.MILLISECONDS.sleep(200);
new Thread(() -> phone.hello(), "A").start();
}
}
答案:
send SMS…
send email…
分析:hello() 方法并不是同步方法,因此不受锁的影响。
4、两部手机,先打印邮件还是短信?
class Phone {
public synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("send email...");
}
public synchronized void sendSMS() {
System.out.println("send SMS...");
}
}
public class Lock8 {
public static void main(String[] args) throws Exception {
Phone phone = new Phone();
Phone phone2 = new Phone();
new Thread(() -> {
try {
phone.sendEmail();
} catch (Exception e) {
e.printStackTrace();
}
}, "A").start();
TimeUnit.MILLISECONDS.sleep(200);
new Thread(() -> phone2.sendSMS(), "A").start();
}
}
答案:
send SMS…
send email…
分析:synchronized锁的是对象,两个对象互不影响。
5、两个静态同步方法,先打印邮件还是短信?
class Phone {
public static synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("send email...");
}
public static synchronized void sendSMS() {
System.out.println("send SMS...");
}
}
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();
TimeUnit.MILLISECONDS.sleep(200);
new Thread(() -> phone.sendSMS(), "A").start();
}
}
答案:
send email…
send SMS…
分析:此时是类锁,锁的是Phone.class。
6、两个静态同步方法,两个手机,先打印邮件还是短信?
class Phone {
public static synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("send email...");
}
public static synchronized void sendSMS() {
System.out.println("send SMS...");
}
}
public class Lock8 {
public static void main(String[] args) throws Exception {
Phone phone = new Phone();
Phone phone2 = new Phone();
new Thread(() -> {
try {
phone.sendEmail();
} catch (Exception e) {
e.printStackTrace();
}
}, "A").start();
TimeUnit.MILLISECONDS.sleep(200);
new Thread(() -> phone2.sendSMS(), "A").start();
}
}
答案:
send email…
send SMS…
分析:static方法全局共享,所以不管有多少手机,访问的都是同一个方法。
7、一个普通同步方法,一个静态同步方法,一部手机,先打印邮件还是短信?
class Phone {
public static synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("send email...");
}
public static synchronized void sendSMS() {
System.out.println("send SMS...");
}
public synchronized void hello() {
System.out.println("send SMS...");
}
}
public class Lock8 {
public static void main(String[] args) throws Exception {
Phone phone = new Phone();
Phone phone2 = new Phone();
new Thread(() -> {
try {
phone.sendEmail();
} catch (Exception e) {
e.printStackTrace();
}
}, "A").start();
TimeUnit.MILLISECONDS.sleep(200);
new Thread(() -> phone.hello(), "A").start();
}
}
答案:
send SMS…
send email…
分析:锁对象不同,一个锁的是Phone.class,一个锁的是this。
8、一个普通同步方法,一个静态同步方法,两部手机,先打印邮件还是短信?
class Phone {
public static synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("send email...");
}
public static synchronized void sendSMS() {
System.out.println("send SMS...");
}
public synchronized void hello() {
System.out.println("send SMS...");
}
}
public class Lock8 {
public static void main(String[] args) throws Exception {
Phone phone = new Phone();
Phone phone2 = new Phone();
new Thread(() -> {
try {
phone.sendEmail();
} catch (Exception e) {
e.printStackTrace();
}
}, "A").start();
TimeUnit.MILLISECONDS.sleep(200);
new Thread(() -> phone2.hello(), "A").start();
}
}
答案:
send SMS…
send email…
分析:同7。