一张图讲解对象锁和关键字synchronized修饰方法(代码块)
2017-10-22 21:01
411 查看
分类:
Java基础(27)
每个对象在出生的时候就有一把钥匙(监视器Monitor),那么被synchronized 修饰的方法相当于给方法加了一个锁,这个方法就可以进行同步,在多线程的时候,不会出现线程安全问题。
注:Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 Monitor。
下面通过一张图片进行讲解:
高清大图
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
37
38
39
40
41
42
43
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
运行结果:
2
3
4
注:
1、运行的结果可能和上图讲的线程流程不同,没有关系,只要理解对象锁和synchronized的核心思想就好,线程的运行本来就是具有随机性这个特点。
2、此段代码是同步方法,其实同步的代码块也是一个道理,同步代码块用synchronized(this)时候,当一个线程访问object的一个synchronized(this)同步代码块的时候,其他线程对object中所有其他的synchronized(this)同步的代码块访问都被阻塞(阻塞的是同步代码块,线程依然可以进入同步代码块的方法)。
上图所示,哪个线程先执行带有synchronized关键字的方法,哪个线程就持有这个方法所属对象的钥匙。其他线程只能处于等待状态。
调用关键字synchronized声明的方法,一定是排队运行的。这才是使用synchronized关键字的作用,排队运行,如果有共享资源的话,那么共享资源的读取就是线程安全的。
如果一个线程持有 object的钥匙,那么其他线程可以访问object对象没有上锁的方法,也就是非synchronized类型的方法。
上图分为三块:Entry Set(进入区) 、The Owner(拥有区)、Wait Set(等待区)。
Entry Set(进入区):表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则迚入拥有者;否则则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。
The Owner(拥有区):表示某一线程成功竞争到对象锁。
Wait Set(等待区):表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。
从图中可以看出,一个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。
上面的内容讲解引自 :Java命令学习系列(二)——Jstack 中关于Monitor的讲解。
如果帅气(美丽)、睿智(聪颖),和我一样简单善良的你看到本篇博文中存在问题,请指出,我虚心接受你让我成长的批评,谢谢阅读!
祝你今天开心愉快!
欢迎访问我的csdn博客,我们一同成长!
“不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!”
博客首页:http://blog.csdn.net/u010648555
分类:
Java基础(27)
每个对象在出生的时候就有一把钥匙(监视器Monitor),那么被synchronized 修饰的方法相当于给方法加了一个锁,这个方法就可以进行同步,在多线程的时候,不会出现线程安全问题。
注:Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 Monitor。
下面通过一张图片进行讲解:
1.一张图片
图片看不清,请点击这里 :高清大图
2.图片对应的代码
import java.util.Date; /** * 测试的object类 * * @author:dufy * @version:1.0.0 * @date 2017/9/29 * @email 742981086@qq.com */ public class ObjectTest { public synchronized void methodA(){ try { System.out.println("This is methodA ...." + Thread.currentThread().getName() + ": " + new Date()); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } public void methodB(){ System.out.println("This is methodB ...." + Thread.currentThread().getName() + ": " + new Date()); } public synchronized void methodC(){ try { System.out.println("This is methodC ...." + Thread.currentThread().getName() + ": " + new Date()); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } }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
37
38
39
40
41
42
43
package com.dufy.concurrentcode; /** * 测试线程类 * * @author:dufy * @version:1.0.0 * @date 2017/9/29 4000 * @email 742981086@qq.com */ public class ThreadTest extends Thread{ public static void main(String[] args) { ObjectTest ot = new ObjectTest(); Thread1 t1 = new Thread1(ot,"thread1"); Thread2 t2 = new Thread2(ot,"thread2"); Thread3 t3 = new Thread3(ot,"thread3"); Thread4 t4 = new Thread4(ot,"thread4"); t1.start(); t2.start(); t3.start(); t4.start(); } static class Thread1 extends Thread{ private ObjectTest objectTest; public Thread1(ObjectTest objectTest,String name){ setName(name); this.objectTest = objectTest; } @Override public void run() { super.run(); objectTest.methodA(); } } static class Thread2 extends Thread{ private ObjectTest objectTest; public Thread2(ObjectTest objectTest,String name){ setName(name); this.objectTest = objectTest; } @Override public void run() { super.run(); objectTest.methodB(); } } static class Thread3 extends Thread{ private ObjectTest objectTest; public Thread3(ObjectTest objectTest,String name){ setName(name); this.objectTest = objectTest; } @Override public void run() { super.run(); objectTest.methodA(); } } static class Thread4 extends Thread{ private ObjectTest objectTest; public Thread4(ObjectTest objectTest,String name){ setName(name); this.objectTest = objectTest; } @Override public void run() { super.run(); objectTest.methodC(); } } }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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
运行结果:
This is methodB ....thread2: Fri Sep 29 23:21:17 CST 2017 This is methodA ....thread1: Fri Sep 29 23:21:17 CST 2017 This is methodC ....thread4: Fri Sep 29 23:21:18 CST 2017 This is methodA ....thread3: Fri Sep 29 23:21:21 CST 20171
2
3
4
注:
1、运行的结果可能和上图讲的线程流程不同,没有关系,只要理解对象锁和synchronized的核心思想就好,线程的运行本来就是具有随机性这个特点。
2、此段代码是同步方法,其实同步的代码块也是一个道理,同步代码块用synchronized(this)时候,当一个线程访问object的一个synchronized(this)同步代码块的时候,其他线程对object中所有其他的synchronized(this)同步的代码块访问都被阻塞(阻塞的是同步代码块,线程依然可以进入同步代码块的方法)。
3.总结
每个对象都有一把锁(对象监视器),关键字synchronized取得锁都是对象锁,而不是把一段代码或方法(函数)当做锁。上图所示,哪个线程先执行带有synchronized关键字的方法,哪个线程就持有这个方法所属对象的钥匙。其他线程只能处于等待状态。
调用关键字synchronized声明的方法,一定是排队运行的。这才是使用synchronized关键字的作用,排队运行,如果有共享资源的话,那么共享资源的读取就是线程安全的。
如果一个线程持有 object的钥匙,那么其他线程可以访问object对象没有上锁的方法,也就是非synchronized类型的方法。
4.Monitor和线程关系
首先看一下线程和 Monitor之间关系,以 及线程的状态转换图。通过图讲解一下整个过程。上图分为三块:Entry Set(进入区) 、The Owner(拥有区)、Wait Set(等待区)。
Entry Set(进入区):表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则迚入拥有者;否则则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。
The Owner(拥有区):表示某一线程成功竞争到对象锁。
Wait Set(等待区):表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。
从图中可以看出,一个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。
上面的内容讲解引自 :Java命令学习系列(二)——Jstack 中关于Monitor的讲解。
5.参考
Java多线程编程核心技术如果帅气(美丽)、睿智(聪颖),和我一样简单善良的你看到本篇博文中存在问题,请指出,我虚心接受你让我成长的批评,谢谢阅读!
祝你今天开心愉快!
欢迎访问我的csdn博客,我们一同成长!
“不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!”
博客首页:http://blog.csdn.net/u010648555
相关文章推荐
- [置顶] 一张图讲解对象锁和关键字synchronized修饰方法(代码块)
- 一张图讲解对象锁和关键字synchronized修饰方法
- 一张图讲解对象锁和关键字synchronized修饰方法
- synchronized关键字修饰对象锁,同步与非同步对该方法的访问及修改
- 当类中的方法全部都是 static 关键字修饰时 ,它的构造方法最好作为 private 私有化,理由是方法全是 static, 不知道的人会去new对象去调用,需要调用构造方法。 但 static的方法直接用类名调用就行!
- java多线程(四)synchronized关键字修饰方法
- JAVA面向对象之代码块 继承 方法的重写 super关键字与重写toString()方法介绍
- Java 多线程:synchronized 关键字 3ff0 用法(修饰类,方法,静态方法,代码块)
- java synchronized关键字的用法以及锁的等级:方法锁、对象锁、类锁
- java synchronized关键字的用法以及锁的等级:方法锁、对象锁、类锁
- 牛客网Java刷题知识点之同步方法和同步代码块的区别(用synchronized关键字修饰)
- Java synchronized关键字的用法以及锁的等级:方法锁、对象锁、类锁
- java中synchronized修饰的方法和代码块
- java synchronized关键字的用法以及锁的等级:方法锁、对象锁、类锁
- 多线程:synchronized 关键字用法(修饰类,方法,静态方法,代码块)
- Java 多线程5:synchronized 关键字用法(修饰类,方法,静态方法,代码块)
- Java中synchronized关键字修饰方法同步的用法详解
- java中synchronized修饰代码块(两种创建线程的方式讲解卖票程序)
- synchronized修饰方法和对象的区别
- java多线程(四)synchronized关键字修饰方法