8锁现象线程彻底理解锁
利用8道题,彻底搞定锁
1.问题一
package com.coding.lock8;
import java.util.concurrent.TimeUnit;
/*
1、标准的访问情况下,先执行 sendEmail 还是 sendSMS
答案:sendEmail
被 synchronized 修饰的方式,锁的对象是方法的调用者,所以说这里两个方法调用的对象是同一个
先调用的先执行!
*/
public class LockDemo01 {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
new Thread(()->{
phone.sendEmail();
},"A").start();
//Thread.sleep(200);
TimeUnit.SECONDS.sleep(2);
new Thread(()->{
phone.sendSMS();
},"B").start();
}
}
class Phone{
public synchronized void sendEmail(){
System.out.println("sendEmail");
}
public synchronized void sendSMS(){
System.out.println("sendSMS");
}
}
2.问题二
package com.coding.lock8;
import java.util.concurrent.TimeUnit;
/*
2、sendEmail休眠3秒后 ,先执行 sendEmail 还是 sendSMS
答案:sendEmail
被 synchronized 修饰的方式,锁的对象是方法的调用者,所以说这里两个方法调用的对象是同一个
先调用的先执行!
*/
public class LockDemo02 {
public static void main(String[] args) throws InterruptedException {
Phone2 phone = new Phone2();
new Thread(()->{
try {
phone.sendEmail();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
//Thread.sleep(200);
TimeUnit.SECONDS.sleep(2);
new Thread(()->{
phone.sendSMS();
},"B").start();
}
}
class Phone2{
public synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println("sendEmail");
}
public synchronized void sendSMS(){
System.out.println("sendSMS");
}
}
3.问题三
package com.coding.lock8;
import java.util.concurrent.TimeUnit;
/*
3、增加一个普通方法,请问先打印那个 sendEmail 还是 hello
答案:hello
新增加的这个方法没有 synchronized 修饰,不是同步方法,不受锁的影响!
*/
public class LockDemo03 {
public static void main(String[] args) throws InterruptedException {
Phone3 phone = new Phone3();
new Thread(()->{
try {
phone.sendEmail();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
//Thread.sleep(200);
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
phone.hello();
},"B").start();
}
}
class Phone3{
public synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("sendEmail");
}
// 没有 synchronized 没有 static 就是普通方式
public void hello(){
System.out.println("hello");
}
}
4.问题四
package com.coding.lock8;
import java.util.concurrent.TimeUnit;
/*
4、两个手机,请问先执行sendEmail 还是 sendSMS
答案:sendSMS
被 synchronized 修饰的方式,锁的对象是调用者;我们这里有两个调用者,两个方法在这里是两个锁
*/
public class LockDemo04 {
public static void main(String[] args) throws InterruptedException {
Phone4 phone1 = new Phone4();
Phone4 phone2 = new Phone4();
new Thread(()->{
try {
phone1.sendEmail();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
//Thread.sleep(200);
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
phone2.sendSMS();
},"B").start();
}
}
class Phone4{
public synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println("sendEmail");
}
public synchronized void sendSMS(){
System.out.println("sendSMS");
}
}
5.问题五
package com.coding.lock8;
import java.util.concurrent.TimeUnit;
//LockDemo05.Class 模板,只有一个 static
//new LockDemo05(),可以创建多个对象
/*
5、两个静态同步方法,同一个手机请问先执行sendEmail 还是 sendSMS
答案:sendEmail
只要方法被 static 修饰,锁的对象就是 Class模板对象,这个则全局唯一!所以说这里是同一个锁
并不是因为synchronized
*/
public class LockDemo05 {
public static void main(String[] args) throws InterruptedException {
Phone5 phone = new Phone5();
new Thread(()->{
try {
phone.sendEmail();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
//Thread.sleep(200);
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
phone.sendSMS();
},"B").start();
}
}
class Phone5{
public static synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println("sendEmail");
}
public static synchronized void sendSMS(){
System.out.println("sendSMS");
}
}
6.问题六
package com.coding.lock8;
import java.util.concurrent.TimeUnit;
//LockDemo05.Class 模板,只有一个 static
//new LockDemo05(),可以创建多个对象
/*
6、两个静态同步方法,两个手机,请问先执行sendEmail 还是 sendSMS
答案:sendEmail
只要方法被 static 修饰,锁的对象就是 Class模板对象,这个则全局唯一!所以说这里是同一个锁
并不是因为synchronized
*/
public class LockDemo06 {
public static void main(String[] args) throws InterruptedException {
Phone6 phone = new Phone6();
Phone6 phone2 = new Phone6();
new Thread(()->{
try {
phone.sendEmail();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
//Thread.sleep(200);
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
phone2.sendSMS();
},"B").start();
}
}
class Phone6{
public static synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println("sendEmail");
}
public static synchronized void sendSMS(){
System.out.println("sendSMS");
}
}
7.问题七
package com.coding.lock8;
import java.util.concurrent.TimeUnit;
//LockDemo05.Class 模板,只有一个 static
//new LockDemo05(),可以创建多个对象
/*
7、一个普通同步方法,一个静态同步方法,只有一个手机,请问先执行sendEmail 还是 sendSMS
答案:sendSMS
synchronized 锁的是这个调用的对象
static 锁的是这个类的Class模板
这里是两个锁!
*/
public class LockDemo07 {
public static void main(String[] args) throws InterruptedException {
Phone7 phone = new Phone7();
new Thread(()->{
try {
phone.sendEmail();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
//Thread.sleep(200);
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
phone.sendSMS();
},"B").start();
}
}
class Phone7{
public static synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println("sendEmail");
}
public synchronized void sendSMS(){
System.out.println("sendSMS");
}
}
8.问题八
package com.coding.lock8;
import java.util.concurrent.TimeUnit;
//LockDemo05.Class 模板,只有一个 static
//new LockDemo05(),可以创建多个对象
/*
7、一个普通同步方法,一个静态同步方法,两个手机,请问先执行sendEmail 还是 sendSMS
答案:sendSMS
synchronized 锁的是这个调用的对象
static 锁的是这个类的Class模板
这里是两个锁!
*/
public class LockDemo08 {
public static void main(String[] args) throws InterruptedException {
Phone8 phone = new Phone8();
Phone8 phone2 = new Phone8();
new Thread(()->{
try {
phone.sendEmail();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
//Thread.sleep(200);
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
phone2.sendSMS();
},"B").start();
}
}
class Phone8{
public static synchronized void sendEmail() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println("sendEmail");
}
public synchronized void sendSMS(){
System.out.println("sendSMS");
}
}
小结
1、new this 调用的这个对象,是一个具体的对象!
2、static class 唯一的一个模板!
在我们编写多线程程序得时候,只需要搞明白这个到底锁的是什么就不会出错了!
synchronized(Demo.class){
}
synchronized(this){
}