从头认识多线程-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


0 0
原创粉丝点击