架构师养成记--2脏读

Posted 司广孟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了架构师养成记--2脏读相关的知识,希望对你有一定的参考价值。

在我们设计程序的时候要考虑问题的整体,不然很容易出现脏读,看示例

 1 /**
 2  * 业务整体需要使用完整的synchronized,保持业务的原子性。
 3  * @author alienware
 4  *
 5  */
 6 public class DirtyRead {
 7 
 8     private String username = "bjsxt";
 9     private String password = "123";
10     
11     public synchronized void setValue(String username, String password){
12         this.username = username;
13         
14         try {
15             Thread.sleep(2000);
16         } catch (InterruptedException e) {
17             e.printStackTrace();
18         }
19         
20         this.password = password;
21         
22         System.out.println("setValue最终结果:username = " + username + " , password = " + password);
23     }
24     
25     public void getValue(){
26         System.out.println("getValue方法得到:username = " + this.username + " , password = " + this.password);
27     }
28     
29     
30     public static void main(String[] args) throws Exception{
31         
32         final DirtyRead dr = new DirtyRead();
33         Thread t1 = new Thread(new Runnable() {
34             @Override
35             public void run() {
36                 dr.setValue("z3", "456");        
37             }
38         });
39         t1.start();
40         Thread.sleep(1000);
41         
42         dr.getValue();
43     }
44     
45     
46     
47 }

在getValue方法前加synchronized关键字可以避免脏读。否则打印出来的结果是下图那样的:

 

实际我们先要的结果应该是这样的:

 

二、数据库的ACID

这里先关注一下ORACLE的一致性读的特性:举个例子,有A和B两个人,A在上午9点的时候对一张很大的表进行查询操作,假设这个查询需要10分钟,B在9点05分的时候对A要查询的这条记录进行了DML操作,将原来的数据值为1改成了2,那么A在9点10分得到的结果一定是1,而不会是2.(做DML操作之前会把原来的值放到UNDO里,A拿到的是UNDO里的值,也有可能抛出snapshot too old异常,但绝不可能把2返回给A)

 

以上是关于架构师养成记--2脏读的主要内容,如果未能解决你的问题,请参考以下文章

架构师养成记--线程基础

架构师养成记--3.synchronized细节问题

架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock

架构师养成记--5.线程之间的通信

架构师养成记--15.Disruptor并发框架

架构师养成记--6.单例和多线程ThreadLocal