标签:
这一章节接着上一章节最后的错误的思路,我们来证明使用整数属性域作为多线程监视器是不同步的。
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; } @Override public void run() { try { myService.updateA(); } catch (InterruptedException e) { e.printStackTrace(); } } } class ThreadFour implements Runnable { private MyService2 myService; public ThreadFour(MyService2 myService) { this.myService = myService; } @Override public 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; } @Override public void run() { try { myService.updateA(); } catch (InterruptedException e) { e.printStackTrace(); } } } class ThreadFour implements Runnable { private MyService2 myService; public ThreadFour(MyService2 myService) { this.myService = myService; } @Override public 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; } @Override public 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; } @Override public 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; } @Override public 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; } @Override public 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.15 证明使用属性域作为多线程监视器是不同步的
标签:
原文地址:http://blog.csdn.net/raylee2007/article/details/51348008