Day9 多线程进阶 2 八锁现象
uwupu 啦啦啦啦啦

8锁现象(加深synchronized锁的理解)

8个关于锁的问题

锁是什么?如何判断锁的是谁!

对象、Class

synchronized若修饰于实例方法,则锁住的是方法的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Demo5_synchronized锁住的是方法的对象 {
//synchronized锁住的是方法的对象
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();//对象
new Thread(()->{phone.sendSms();},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{phone.call();},"B").start();
//结果
/*
发短信
打电话
*/
/*
解释:A线程启动后,synchronized锁住了对象phone,B线程启动后,必须等待A线程结束后,才会开始执行。
*/
}

}

class Phone{

public synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}

一个对象加锁之后,不影响没有synchronized修饰的方法的正常执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Demo6_synchronized锁住对象后_没有synchronized修饰的方法正常执行 {
//synchronized锁住的是方法的对象
public static void main(String[] args) throws InterruptedException {
Phone2 phone = new Phone2();//对象
new Thread(()->{phone.sendSms();},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{phone.hello();},"B").start();
//结果
/*
Hello
发短信
*/
/*
解释:A线程启动后,synchronized锁住了对象phone,B线程启动后,hello()方法未用synchronized修饰,不受锁的影响,正常执行。
*/
}
}
class Phone2{

public synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public void hello(){//不用synchronized修饰
System.out.println("Hello");
}
}

两个对象 两个同步方法 互不影响

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Demo7_synchronized_两个对象两个同步方法 {
public static void main(String[] args) throws InterruptedException {
Phone3 phone1 = new Phone3();
Phone3 phone2 = new Phone3();
new Thread(()->{phone1.sendSms();},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{phone2.call();},"B").start();
//结果
/*
打电话
发短信
*/
/*
解释:A线程启动后,synchronized锁住了对象phone1,B线程启动后,synchronized锁住了对象phone2,两者互不影响,正常执行。
A线程的sendSms()方法中有sleep,相对输出要比B线程的输出方法要晚。
*/
}
}
class Phone3{

public synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}

静态同步方法锁住的是类的Class对象,不影响实例方法的正常执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Demo8_静态同步方法锁住的是类的Class对象_不影响实例方法的正常执行 {
public static void main(String[] args) throws InterruptedException {
Phone4 phone = new Phone4();
new Thread(() -> {
phone.sendSms();
}, "A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
phone.call();
}, "B").start();
//结果
/*
打电话
发短信
*/
/*
解释:A线程启动后,synchronized锁住了类Phone4的Class对象,B线程启动后,synchronized锁住了对象phone,两者互不影响,正常执行。
A线程的sendSms()方法中有sleep,相对输出要比B线程的输出方法要晚。
*/
}
}
class Phone4 {

public static synchronized void sendSms() {//静态同步方法
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}

public synchronized void call() {
System.out.println("打电话");
}
}

小结

同步实例方法锁住的是调用者/当前对象,会影响当前对象的所有同步实例方法的正常执行。

静态同步实例方法锁住的是类模板对象Class,会影响类的所有类方法的正常执行。

其他

TimeUnit

设置延迟的类,(用来代替Thread.sleep()

方法 介绍
TimeUnit.SECONDS.sleep(timeout) 延时,单位:秒
TimeUnit.DAYS.sleep(timeout) 延时,单位:天
TimeUnit.HOURS.sleep(timeout); 延时,单位:小时
 评论