标签:
这一章节我们来讨论一下解决由同步的synchronized (newobject()) 引起的脏读的方法。
1.造成上面脏读的原因:多线程多方法同时访问并修改某个属性域
2.解决思路
顺着上面的原因,笔者提出两种不是方法的方法
(1)只能单线程单方法访问并修改某个属性域这样就保证了执行的顺序(也就是需要同步所有访问并修改的步骤)(缺点:性能低下,优点:数据的强一致性)
(2)在多线程多方法的情况下,只能够访问多个属性域,不能够同时访问并修改某一个单一的属性域(根本目的就是分开运算,但是,在生产环境中,的确很难把一个属性域分成2个来运算,所以,笔者更趋向于第一种方法)
3.代码清单
(1)第一个思路
package com.ray.deepintothread.ch02.topic_15; /** * * @author RayLee * */ public class SolutionOfDirtyRead { 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.update(); } 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.update(); } 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); } } } public synchronized void update() throws InterruptedException { updateA(); updateB(); } }
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-0 9
Thread-1 10
Thread-1 11
Thread-1 12
Thread-1 13
Thread-1 14
Thread-1 15
Thread-1 16
Thread-1 17
Thread-1 18
Thread-1 19
我们把updateA和updateB组合成为一个方法, 然后做方法级的同步,或者将两个方法组合成方法块的同步,这样,输出的结果就可以是同步的,不会出现脏读
(2)第二种思路
package com.ray.deepintothread.ch02.topic_15; /** * * @author RayLee * */ public class SolutionOfDirtyRead2 { public static void main(String[] args) throws InterruptedException { MyService myService = new MyService(); ThreadOne threadOne = new ThreadOne(myService); Thread thread = new Thread(threadOne); thread.start(); ThreadTwo threadTwo = new ThreadTwo(myService); Thread thread2 = new Thread(threadTwo); thread2.start(); } } class ThreadOne implements Runnable { private MyService myService; public ThreadOne(MyService myService) { this.myService = myService; } @Override public void run() { try { myService.updateA(); } catch (InterruptedException e) { e.printStackTrace(); } } } class ThreadTwo implements Runnable { private MyService myService; public ThreadTwo(MyService myService) { this.myService = myService; } @Override public void run() { try { myService.updateB(); } catch (InterruptedException e) { e.printStackTrace(); } } } class MyService { private Integer id1 = 0; private Integer id2 = 0; public void updateA() throws InterruptedException { synchronized (this) { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + " id1:" + id1++); Thread.sleep(50); } } } public void updateB() throws InterruptedException { synchronized (this) { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + " id2:" + id2++); Thread.sleep(100); } } } }
Thread-0 id1:0
Thread-0 id1:1
Thread-0 id1:2
Thread-0 id1:3
Thread-0 id1:4
Thread-1 id2:0
Thread-1 id2:1
Thread-1 id2:2
Thread-1 id2:3
Thread-1 id2:4
虽然输出的结果是同步的,但是也是上面所说的,一个属性域(一般是某个数的运算或者某种状态的运算)是很难分开来的。当然,如果可以分开来,这是最优解,因为既保证了同步,也保证了数据的强一致性。
总结:这一章节主要讨论了解决由同步的synchronized (newobject()) 引起的脏读的方法。
这一章节就到这里,谢谢
------------------------------------------------------------------------------------
我的github:https://github.com/raylee2015/DeepIntoThread
目录:http://blog.csdn.net/raylee2007/article/details/51204573
从头认识多线程-2.14 解决由同步的synchronized (newobject()) 引起的脏读的方法
标签:
原文地址:http://blog.csdn.net/raylee2007/article/details/51340392