• 高并发编程系列(一)


    高并发编程系列(一)

    High concurrency programming series

    对某个对象加锁

    public class Ta {
    
        /**
         * synchronized keyword 
         * Locks an object
         */
    
        private int count = 10;
    
        private Object o = new Object();
    
        public void m(){
            synchronized(o){
                count--;
                System.out.println(Thread.currentThread().getName() + "count:" + count);
            }
        }
    
    }
    

    等同于在方法的代码执行时要synchronized

    public class Tb {
    
        /**
         * Is equivalent to synchronized when the method's code executes.
         */
    
        private int count = 10;
    
        private Object o = new Object();
    
        public synchronized void m() {
                count--;
                System.out.println(Thread.currentThread().getName() + "count:" + count);
        }
    
    }
    

    任何线程执行下面代码,必须要拿到this 的锁,
    记住锁定的时对象 不是代码块 表面看着是代码块

    public class Tc {
    
        /**
         * Any thread that executes the following code must get the lock for this,
         * Remember that the object that is locked is not a block of code and it looks like a block of code
         */
    
        private int count = 10;
    
        public void m() {
            synchronized(this) {
                count--;
                System.out.println(Thread.currentThread().getName() + "count:" + count);
            }
        }
    
    }
    

    放在静态方法上面,由于静态没有this可以锁定,不需要new 出对象,运用了反射.

    public class Td {
    
        /**
         * On the static method, because static no this can be locked, do not need to new out of the object, the use of reflection.
         */
    
        private static int count = 10;
    
        private Object o = new Object();
    
        public synchronized static void m() {
                count--;
                System.out.println(Thread.currentThread().getName() + "count:" + count);
        }
    
        public void mm() {
            synchronized(Td.class) {  //考虑一下这里写 synchronized (this)  是否可以  不可以
                count--;
                System.out.println(Thread.currentThread().getName() + "count:" + count);
            }
        }
    
    }
    
    public class Te implements Runnable {
    
        private int count = 10;
    
        @Override
        public synchronized void run() {
            count --;
            System.out.println(Thread.currentThread().getName() + "count:" + count);
        }
    
        public static void main(String[] args) {
    
            Te t = new Te();
            for (int i = 0; i<5;i++){
                new Thread(t,"THREAD" + i).start();
            }
    
        }
        
    }
    

    m1不影响m2,同步方法不影响其他方法,m2 不需要锁.

    public class Tf {
    
        /**
         *
         * M1 does not affect m2, synchronous methods do not affect other methods, and m2 does not need a lock.
         */
    
        public synchronized void m1() {
            System.out.println(Thread.currentThread().getName() + "m1.start....");
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "m1.end");
        }
    
        public void m2() {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "m2");
        }
    
        public static void main(String[] args) {
            Tf t = new Tf();
    
            new Thread(()->t.m1()).start();
            new Thread(()->t.m2()).start();
    
            /*new Thread(t::m1,"t1").start();
            new Thread(t::m2,"t2").start();*/
    
           /* new Thread(new Runnable() {
                @Override
                public void run() {
                    t.m1();
                }
            });*/
    
        }
    
    }
    

    对业务写方法加锁.
    对业务读方法不加锁.
    容易产生脏读问题(dirtyRead).

    public class Tg {
    
        /**
         *
         * Locks the business write method.
         * Business read methods are not locked.
         * DirtyRead is easy to produce.
         * No two seconds sleep, no problem, plus there's a dirty read on the read,
         * there's a block of code between two seconds that might be executed by some other program that's not locked.
         * Lock or no lock depends on the business.
         * Tg For the account class  It has a name and a balance
         *
         */
    
        String name;
        double balance;
    
        public synchronized void set(String name, double balance) {
            this.name = name;
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            this.balance = balance;
        }
    
        public /*synchronized*/ double getBalance(String name) {
            return this.balance;
        }
    
        public static void main(String[] args) {
            Tg t = new Tg();
            new Thread(()->t.set("掌上编程",100.0)).start();
    
            try{
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println(t.getBalance("掌上编程"));
    
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(t.getBalance("掌上编程"));
    
        }
    
    }
    

    运行结果

    一个同步方法可以调用另外一个同步方法,一个线程已经拥有某个对象,再次申请的时候仍然会得到该对象的锁,
    也就是说synchronized 获得锁是可重入的。

    public class Th {
    
        /**
         *
         * One synchronized method can call another, and a thread that already owns an object will still get its lock when it requests it again.
         * That is, synchronized acquired locks are reentrant.
         */
    
        synchronized void m1() {
            System.out.println("m1.start");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            m2();
        }
    
        synchronized void m2() {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("m2");
        }
    
    }
    

    一个同步的方法可以调用另外一个同步方法.一个线程已经拥有某个对象的锁,再次申请的时候仍然会得到该对象的锁.也就是说 synchronized获得的锁是可重入的.这里是继承中有可能发生的情形,子类调用父类的同步方法.

    public class Ti {
        synchronized void m() {
        
            System.out.println("m.start");
            try{
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("m.end");
        }
    
        public static void main(String[] args) {
            new TiTi().m();
        }
    
    }
    
    class TiTi extends Ti {
    
        @Override
        synchronized void m(){
            System.out.println("child m start");
            super.m();
            System.out.println("child m end");
        }
    
    }
    

    运行结果

  • 相关阅读:
    PHP导出数据到淘宝助手CSV的方法分享
    创业日志:壹百款购物客户中心正式上线啦!
    THINKPHP+JS缩放图片式截图的实现
    入园3年来的感慨
    CentOS 5 全攻略 一步一步配置详解
    创业日记:进入电子商务领域,需未雨绸缪,更要步步谨慎
    IT商悟读书笔记
    震惊的事情一波接一波的,找自己的FREE
    创业日记:微团队,技术应用思考
    博客园我回来了!
  • 原文地址:https://www.cnblogs.com/mzdljgz/p/11635585.html
Copyright © 2020-2023  润新知