从头认识多线程-2.16 证明使用整数属性域作为多线程监视器是不同步的
来源:互联网 发布:淘宝宝贝品牌怎么填 编辑:程序博客网 时间:2024/06/06 02:50
这一章节接着上一章节最后的错误的思路,我们来证明使用整数属性域作为多线程监视器是不同步的。
1.用同一个属性域作为多线程监视器,是不同步的
package com.ray.deepintothread.ch02.topic_16;/** * * @author RayLee * */public class DirtyReadWithSynchBlock {public static void main(String[] args) throws InterruptedException {MyService2 myService = new MyService2();ThreadThree threadThree = new ThreadThree(myService);Thread thread = new Thread(threadThree);thread.start();ThreadFour threadFour = new ThreadFour(myService);Thread thread2 = new Thread(threadFour);thread2.start();}}class ThreadThree implements Runnable {private MyService2 myService;public ThreadThree(MyService2 myService) {this.myService = myService;}@Overridepublic void run() {try {myService.updateA();} catch (InterruptedException e) {e.printStackTrace();}}}class ThreadFour implements Runnable {private MyService2 myService;public ThreadFour(MyService2 myService) {this.myService = myService;}@Overridepublic void run() {try {myService.updateB();} catch (InterruptedException e) {e.printStackTrace();}}}class MyService2 {private Integer id = 0;public void updateA() throws InterruptedException {synchronized (id) {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " " + id++);Thread.sleep(50);}}}public void updateB() throws InterruptedException {synchronized (id) {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " " + id++);Thread.sleep(100);}}}}
输出:
Thread-0 0
Thread-1 1
Thread-0 2
Thread-1 3
Thread-0 3
Thread-0 4
Thread-0 5
Thread-1 5
Thread-1 6
Thread-1 7
从上面的输出可以得出相应结论
另一个例子:
package com.ray.deepintothread.ch02.topic_16;/** * * @author RayLee * */public class DirtyReadWithSynchBlock {public static void main(String[] args) throws InterruptedException {MyService2 myService = new MyService2();ThreadThree threadThree = new ThreadThree(myService);Thread thread = new Thread(threadThree);thread.setName("thread A");thread.start();ThreadFour threadFour = new ThreadFour(myService);Thread thread2 = new Thread(threadFour);thread2.setName("thread B");thread2.start();}}class ThreadThree implements Runnable {private MyService2 myService;public ThreadThree(MyService2 myService) {this.myService = myService;}@Overridepublic void run() {try {myService.updateA();} catch (InterruptedException e) {e.printStackTrace();}}}class ThreadFour implements Runnable {private MyService2 myService;public ThreadFour(MyService2 myService) {this.myService = myService;}@Overridepublic void run() {try {myService.updateB();} catch (InterruptedException e) {e.printStackTrace();}}}class MyService2 {private Integer id = 0;public void updateA() throws InterruptedException {synchronized (id) {for (int i = 0; i < 5; i++) {System.out.println("id:" + id);System.out.println(Thread.currentThread().getName() + " " + id++);Thread.sleep(50);System.out.println("-------------------");}}}public void updateB() throws InterruptedException {synchronized (id) {for (int i = 0; i < 5; i++) {System.out.println("id:" + id);System.out.println(Thread.currentThread().getName() + " " + id++);Thread.sleep(100);System.out.println("-------------------");}}}}
输出:
id:0
thread A 0
id:1
thread B 1
-------------------
id:2
thread A 2
-------------------
id:3
thread A 3
-------------------
id:4
thread B 4
-------------------
id:5
thread A 5
-------------------
-------------------
id:6
id:6
thread B 6
thread A 7
-------------------
-------------------
id:8
thread B 8
-------------------
id:9
thread B 9
-------------------
从输出的结果,特别看到中间的id=6的时候,threadA和threadB计算的结果,就不言而喻了。
2.伪synchronized (newobject())同步的例子
package com.ray.deepintothread.ch02.topic_16;/** * * @author RayLee * */public class SynchBlock {public static void main(String[] args) throws InterruptedException {MyService myService = new MyService();int id = 1;ThreadOne threadOne = new ThreadOne(myService, id);Thread thread = new Thread(threadOne);thread.start();ThreadTwo threadTwo = new ThreadTwo(myService, id);Thread thread2 = new Thread(threadTwo);thread2.start();}}class ThreadOne implements Runnable {private MyService myService;private int id = 0;public ThreadOne(MyService myService, int id) {this.myService = myService;this.id = id;}@Overridepublic void run() {try {myService.updateA(id);} catch (InterruptedException e) {e.printStackTrace();}}}class ThreadTwo implements Runnable {private MyService myService;private int id = 0;public ThreadTwo(MyService myService, int id) {this.myService = myService;this.id = id;}@Overridepublic void run() {try {myService.updateB(id);} catch (InterruptedException e) {e.printStackTrace();}}}class MyService {public void updateA(Integer id) throws InterruptedException {synchronized (id) {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " " + id++);Thread.sleep(50);}}}public void updateB(Integer id) throws InterruptedException {synchronized (id) {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " " + id++);Thread.sleep(100);}}}}
输出:
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Thread-1 5
看上去上面的结果是同步的,而且看上去,我们也是对于同一个属性域进行同步访问和修改,但是,其实不是的。
我们上面的步骤如下:
(1)赋值给每一个线程的id
(2)多线程进行访问与修改
实际上我们一直访问和修改的是线程对象里面的id,而不是在main里面的id,我们将上面的代码简化,然后大家再看看
package com.ray.deepintothread.ch02.topic_16;/** * * @author RayLee * */public class SynchBlock2 {public static void main(String[] args) throws InterruptedException {MyService3 myService = new MyService3();ThreadFive threadFive = new ThreadFive(myService);Thread thread = new Thread(threadFive);thread.start();ThreadSix threadSix = new ThreadSix(myService);Thread thread2 = new Thread(threadSix);thread2.start();}}class ThreadFive implements Runnable {private MyService3 myService;private int id = 1;public ThreadFive(MyService3 myService) {this.myService = myService;}@Overridepublic void run() {try {myService.updateA(id);} catch (InterruptedException e) {e.printStackTrace();}}}class ThreadSix implements Runnable {private MyService3 myService;private int id = 1;public ThreadSix(MyService3 myService) {this.myService = myService;}@Overridepublic void run() {try {myService.updateB(id);} catch (InterruptedException e) {e.printStackTrace();}}}class MyService3 {public void updateA(Integer id) throws InterruptedException {synchronized (id) {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " " + id++);Thread.sleep(50);}}}public void updateB(Integer id) throws InterruptedException {synchronized (id) {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " " + id++);Thread.sleep(100);}}}}
输出:
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Thread-1 5
输出结果跟上面的没有区别,因此,得出结论是,方法里面修改的是每一个线程对象里面的id,是两个不同的属性域,这当然不会出现脏读的情况。
总结:这一章节我们证明了使用整数属性域作为多线程监视器是不同步的。
这一章节就到这里,谢谢
------------------------------------------------------------------------------------
我的github:https://github.com/raylee2015/DeepIntoThread
目录:http://blog.csdn.net/raylee2007/article/details/51204573
- 从头认识多线程-2.16 证明使用整数属性域作为多线程监视器是不同步的
- 从头认识多线程-2.24 修改监视器对同步的影响
- 从头认识多线程-2.11 通过同步代码块证明synchronized标记的是对象锁
- 从头认识多线程-1.12 suspend和resume缺点-不同步
- 从头认识多线程-1.1 多线程的创建
- 从头认识多线程-目录
- 从头认识多线程-目录
- 从头认识多线程-2.5 锁的可重入性
- 从头认识多线程-4.2 对象逸出的其他解决方案-主要是ThreadLocal的应用
- 从头认识多线程-2.7 同步是不具备继承性的
- 从头认识多线程-2.25 synchronized同步方法在jvm是怎样执行的?
- 从头认识多线程-2.26 synchronized同步代码块在jvm是怎样执行的?
- 从头认识java-17.1 多线程
- 从头认识多线程-1.3 currentThread()
- 从头认识多线程-1.14 优先级
- 从头认识多线程-2.19 synchronized (new object())同步时各种不同类别的监视器以及其引起的问题(常量池的影响)
- 从头认识多线程-3.1 使用volatile解决异步死循环
- 从头认识多线程-3.2 使用volatile声明的变量的写操作是非原子性的
- Linux中线程与CPU核的绑定
- html5图形组合
- IBM Watson物联网平台的两个MQTT工具
- IC卡和ID卡的区别以及相同之处各是什么?
- Android面试题
- 从头认识多线程-2.16 证明使用整数属性域作为多线程监视器是不同步的
- yum默认软件安装路径
- CSS的line-height属性
- 图论-最短路-BF算法
- Linux学习之文件搜索命令
- Linux 25周年:与创始人Linus Torvalds对话
- python+scapy 抓包与解析
- fdisk -l 显示信息详解
- em与px