zoukankan      html  css  js  c++  java
  • 14_synchronized深入

    【脏读】

    对于对象同步和异步的方法,我们在设计程序的时候,一定要考虑问题的整体,不然会出现不一致的错误,最经典的错误的就是脏读(dirty read)。

    【实例代码】

    package com.higgin.part4;
    
    /**
     * 在我们对一个对象的方法加锁的时候,需要考虑业务的整体性。
     * 本例子中的setValue或getValue必须同时加上synchronized同步关键字,办证业务的原子性,不然会出现业务错误 
     */
    public class DirtyRead {
        private String username="zhangsan";
        private String password="123";
        
        public synchronized void setValue(String username,String password){
            this.username=username;
            try {
                Thread.sleep(2000);   //延时2秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.password=password;
            System.out.println("setValue最终结果【 username = "+username+", password = "+password + "");
        }
        
        /**
         * 加和不加synchronized有区别
         */
        public void getValue(){
            System.out.println("getValue最终结果【 username = "+username+", password = "+password + "");
        }
        
        public static void main(String[] args) throws InterruptedException {
            final DirtyRead dr = new DirtyRead();
            
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    dr.setValue("lisi", "456");
                }
            });
            t1.start();   //t1线程去设置值
            Thread.sleep(1000);
            dr.getValue();    //相当于main线程去读取值
        }
    }

    【运行结果:不加synchronized】

    【运行结果:加上synchronized】

    【关于synchronized代码块】

    直接使用synchronized声明的方法是在有些情况下是有弊端的,比如A线程调用的同步方法执行一个时间很长的任务,那么B线程就必须等待比较长的时间才能执行,这样的情况下可以使用synchronized代码块去优化代码执行时间,也就是通常所说的减小锁的粒度。

    【synchronized代码块加锁:对象锁、类锁、任意对象锁】

    package com.higgin.part6;
    
    public class DiffLock {
        
        public void method1(){
            synchronized(this){  //对象锁
                System.out.println("method1");
            }
        }
        
        public void method2(){
            synchronized(DiffLock.class){  //类锁
                System.out.println("method2");
            }
        }
        
        private Object obj = new Object();
        public void method3(){    
            synchronized(obj){     //任意对象锁
                System.out.println("method3");
            }
        }
    }

    【关于String类型的锁】

    注意不要使用String的常量加锁,容易出现死循环问题。

    package com.higgin.part6;
    
    /**
     * synchronized代码块对字符串的锁,注意String常量池的缓存功能
     */
    public class StringLock {
    
        public void method() {
            //分别使用new String("abc")和"abc"
            synchronized ("abc") {  //这里是一个String类型的常量锁
                try {
                    while(true){
                        System.out.println("当前线程 : "  + Thread.currentThread().getName() + "开始");
                        Thread.sleep(1000);        
                        System.out.println("当前线程 : "  + Thread.currentThread().getName() + "结束");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        
        public static void main(String[] args) {
            final StringLock stringLock = new StringLock();
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    stringLock.method();
                }
            },"t1");
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    stringLock.method();
                }
            },"t2");
            
            t1.start();  //这里本质上t1、t2抢占的是同一个String锁("abc"),t1一直未释放锁,导致t2无法获得锁执行代码
            t2.start();
        }
    }

    【运行结果:使用"abc"常量字符串作为锁,t2线程一直无法执行】

    【运行结果:使用new String("abc")非常量字符作为锁,t2和t1竞争执行】

  • 相关阅读:
    ASP.NET Web API中通过URI显示实体中的部分字段
    ASP.NET Web API中把分页信息放Header中返回给前端
    写一个针对IQueryable<T>的扩展方法支持动态排序
    Perl处理和收走子进程(退出状态码和wait)
    Perl多进程
    Perl信号处理
    大话西游之大圣娶亲中的至尊宝和紫霞仙子
    Perl List::Util模块用法详解
    Python面向对象:杂七杂八的知识点
    Python迭代和解析(5):搞懂生成器和yield机制
  • 原文地址:https://www.cnblogs.com/HigginCui/p/6691321.html
Copyright © 2011-2022 走看看