线程的业务原子性

  • 对于对象的同步和异步的方法,我们在设计自己的程序的时候,一定要考虑问题的整体性,不然就会出现数据不一致的错误,很经典的错误就是脏读(dirtyread)
  • 程序实例:
  • public class DirtyRead {
    
        private String username = "z3";
        private String password = "123";
    
    
        public synchronized void setValue(String username, String password) {
            this.username = username;
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.password = password;
    
            System.out.println("setValue最终结果: username=" + username + ",password=" + password);
        }
    
        public void getValue() {
            System.out.println("getValue方法结果: username=" + this.username + ",password=" + password);
        }
    
        public static void main(String[] args) {
            final DirtyRead dr = new DirtyRead();
            new Thread(new Runnable() {
                public void run() {
                    dr.setValue("w5", "456");
                }
            }).start();
    
            dr.getValue();
        }
    }

    运行结果:

    • getValue方法结果: username=z3,password=123

    • setValue最终结果: username=w5,password=456

    • 结果分析:我们在通过setValue方法中设置的值,结果取出来的不是我们设置的值,说明了数据脏读,主线程和子线程在数据操作时不是业务原子性的。

  • 当我们给getValue()方法加上synchronized后,此时两个方法用的是同一把锁!

  • public class DirtyRead {
    
        private String username = "z3";
        private String password = "123";
    
    
        public synchronized void setValue(String username, String password) {
            this.username = username;
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.password = password;
    
            System.out.println("setValue最终结果: username=" + username + ",password=" + password);
        }
    
        public synchronized void getValue() {
            System.out.println("getValue方法结果: username=" + this.username + ",password=" + password);
        }
    
        public static void main(String[] args) {
            final DirtyRead dr = new DirtyRead();
            new Thread(new Runnable() {
                public void run() {
                    dr.setValue("w5", "456");
                }
            }).start();
    
            dr.getValue();
        }
    }
    

    运行结果:

    setValue最终结果: username=w5,password=456
    getValue方法结果: username=w5,password=456

 

 

转载于:https://my.oschina.net/sxshifeifei/blog/889610

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值