zoukankan      html  css  js  c++  java
  • Java马士兵高并发编程视频学习笔记(一)

    1.同一个资源,同步和非同步的方法可以同时调用

    package com.dingyu;
    
    public class Y {
        public synchronized void m1() {
            System.out.println(Thread.currentThread().getName() + " m1 begin---------");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " m1 end---------");
        }
    
        public void m2() {
            System.out.println(Thread.currentThread().getName() + " m2 begin---------");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " m2 end---------");
        }
        public static void main(String[] args) {
            Y t = new Y();
    //        new Thread(()->t.m1(),"t1").start();
    //        new Thread(()->t.m2(),"t2").start();
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    t.m1();
                    
                }
            },"t1").start();;
        new Thread(new Runnable() {
                
                @Override
                public void run() {
                    t.m2();
                    
                }
            },"t2").start();;
        }
    }

    可以看到t1先执行,如果不能同时调用那么t2是不能执行的,必须等t1结束,释放锁后才能调用,但这里t2确先执行了,所以是可以同时调用的。

    2.对业务写代码进行加锁,对读代码不进行加锁,会产生脏读

      

    package com.dingyu;
    
    public class U {
        private String name;
        private double banlance;
    
        public synchronized void set(String name, double balance) {
            this.name = name;
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.banlance = balance;
        }
    
        public double getBalance() {
            return banlance;
        }
    
        public static void main(String[] args) {
            U u = new U();
            new Thread(() -> u.set("zhangsan", 500)).start();
            System.out.println(u.getBalance());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(u.getBalance());
        }
    }

    3.同线程内一个同步方法可以去调用另一个同步方法(重入锁 还有一种重入锁就是子类调用父类的同步方法)

    package com.dingyu;
    
    public class I {
        public synchronized void m1() {
            System.out.println("m1 start");
            m2();
            System.out.println("m1 end");
        }
    
        private synchronized void m2() {
            System.out.println("m2 start");
            System.out.println("m2 end");
        }
    
        public static void main(String[] args) {
            I i = new I();
            new Thread(() -> i.m1()).start();
        }
    
    }

    4.模拟一个简单的死锁

    package com.dingyu;
    
    public class DeadLock {
        private Object o1 = new Object();
        private Object o2 = new Object();
    
        public void m1() {
            synchronized (o1) {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                synchronized (o2) {
                    System.out.println("如果出现这句话表示没有死锁");
                }
            }
            
        }
        
        public void m2() {
            synchronized(o2) {
                
                synchronized (o1) {
                    System.out.println("如果出现这句话表示没有死锁");
                }
                
            }
            
        }
        public static void main(String[] args) {
            DeadLock deadLock=new DeadLock();
            new Thread(()->deadLock.m1()).start();
            new Thread(()->deadLock.m2()).start();
        }
    }

    5.如果执行同步方法中出现异常,那么就会自动释放锁,如果不想释放锁,加上try catch

    package com.dingyu;
    
    public class ReleaseLock {
        private int count = 0;
        private int i = 0;
    
        public synchronized void m1() {
            while (true) {
                System.out.println(Thread.currentThread().getName() + " " + count++);
                if (count % 10 == 0)
                    i = 1 / 0;
            }
        }
    
        public static void main(String[] args) {
            ReleaseLock releaseLock = new ReleaseLock();
            new Thread(() -> releaseLock.m1(), "t1").start();
            new Thread(() -> releaseLock.m1(), "t2").start();
        }
    }

     6.volatile关键字(无锁同步)

    volatile关键字 每个线程都有自己的一小块内存,执行的时候会把变量copy过来,修改了后在写回对象,

    执行m1方法的线程把 running读到内存里,与此同时主线程也把running读到内存,并进行修改,写回对象为false

    但是执行m1的线程里的内存一直都是true啊(因为太忙了没空去刷新)所以会形成死循环,

    volatile就是当running改了之后 *立马去通知其他线程,你们记得去主存刷新一下,一刷新,running为false,退出while循环。

    package com.dingyu;
    /**
     * volatile关键字   每个线程都有自己的一小块内存,执行的时候会把变量copy过来,修改了后在写回对象,
     * 执行m1方法的线程把 running读到内存里,与此同时主线程也把running读到内存,并进行修改,写回对象为false
     * 但是执行m1的线程里的内存一直都是true啊(因为太忙了没空去刷新)所以会形成死循环,volatile就是当running改了之后
     * 立马去通知其他线程,你们记得去主存刷新一下,一刷新,running为false,退出while循环。
     * @author dingyu
     *
     */
    public class VolatileDemo {
        private volatile boolean running = true;
    
        public void m1() {
            System.out.println("m1 start");
            while (running) {
                
            }
            System.out.println("m1 end");
        }
    
        public static void main(String[] args) {
            VolatileDemo volatileDemo = new VolatileDemo();
            new Thread(() -> volatileDemo.m1()).start();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            volatileDemo.running = false;
    
        }
    }

    7.voliatile 不能保证原子性 不能替换synchronized

    package com.dingyu;
    
    /**
     * voliatile 不能保证原子性 不能替换synchronized
     * 
     * @author dingyu
     *
     */
    public class VolatileDemo02 {
        public volatile int count = 0;
    
        public void m1() {
            for (int i = 0; i <= 10000; i++)
                count++;
        }
    
        public static void main(String[] args) {
            VolatileDemo02 volatileDemo02 = new VolatileDemo02();
            for (int i = 0; i < 3; i++) {
                new Thread(() -> volatileDemo02.m1()).start();
            }
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(volatileDemo02.count);
        }
    }

     8.多个原子类的方法之间不具备原子性

    package com.dingyu;
    
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * 原子类 具有原子性,但两个原子类的方法之间不具备原子性
     * 
     * @author dingyu
     *
     */
    public class AtomicDemo {
        private AtomicInteger count = new AtomicInteger();
    
        public void m1() {
            for (int i = 0; i < 100; i++) {            
                count.incrementAndGet();
                //两个原子类的方法之间不具备原子性
                count.incrementAndGet();
            
            }
        }
    }

    9.原子类的不具备可见性

    package com.dingyu;
    
    import java.util.concurrent.atomic.AtomicBoolean;
    
    public class AtomicDemo02 {
        public AtomicBoolean running = new AtomicBoolean(true);
    
        public void m1() {
            while (running.get()) {
    
            }
        }
    
        public static void main(String[] args) {
            AtomicDemo02 demo02 = new AtomicDemo02();
            new Thread(()->demo02.m1()).start();
            demo02.running.set(false);
        }
    }

    10.锁是锁在堆内存的那个对象上,而不是引用

    package com.dingyu;
    
    /**
     * 锁是锁在堆内存的那个对象上,而不是引用
     * 
     * @author dingyu
     *
     */
    public class ChangeReference {
        public Object o = new Object();
    
        public void m1() {
            //锁o
            synchronized (o) {
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName());
                }
            }
        }
    
        public static void main(String[] args) {
            ChangeReference changeReference = new ChangeReference();
            new Thread(() -> changeReference.m1(), "t1").start();//启动一个线程 叫t1
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            changeReference.o = new Object();//引用变了
            new Thread(() -> changeReference.m1(),"t2").start();//启动线程 t2
        }
    }

     11.不要锁字符串常量

    package com.dingyu;
    /**
     * 不要锁字符串常量
     * @author dingyu
     *
     */
    public class SynchronizedString {
        private String s1 = "hello";
        private String s2 = "hello";
    
        public void m1() {
            synchronized (s1) {
                while(true) {}
            }
        }
    
        public void m2() {
            synchronized (s2) {
                System.out.println("m2 start");
            }
        }
    
        public static void main(String[] args) {
            SynchronizedString synchronizedString = new SynchronizedString();
            new Thread(()->synchronizedString.m1()).start();
            new Thread(()->synchronizedString.m2()).start();
        }
    }

    12.wait 让线程暂停,释放锁, notify 唤醒线程,不释放锁

    package com.dingyu2;
    
    /**
     * wait 让线程暂停,释放锁, notify 唤醒线程,不释放锁
     * 
     * @author dingyu
     *
     */
    public class WaitAndNotyifyDemo {
        private volatile int count = 0;
        private Object lock = new Object();
    
        public void m1() {
            synchronized (lock) {
                System.out.println("m1 start");
                for (int i = 0; i < 10; i++) {
                    count++;
                    System.out.println(count);
                    if (count == 5) {
                        lock.notify();
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
    
            }
        }
    
        public void m2() {
            synchronized (lock) {
                System.out.println("m2 start");
                if (count != 5) {
                    try {
                        System.out.println("m2 在等着 但把锁释放了");
                        lock.wait();                    
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("m2 end");
                lock.notify();
            }
        }
    
        public static void main(String[] args) {
            WaitAndNotyifyDemo waitAndNotyifyDemo = new WaitAndNotyifyDemo();
            new Thread(() -> waitAndNotyifyDemo.m2()).start();
            new Thread(() -> waitAndNotyifyDemo.m1()).start();
        }
    }
  • 相关阅读:
    Android面试题
    java面试题大全
    关于索引的sql语句优化之降龙十八掌
    java动态代理的实现
    java动态代理
    进程与线程
    SqlServer聚合函数
    2015年创业中遇到的技术问题:21-30
    hadoop集群ambari搭建(2)之制作hadoop本地源
    Android录屏命令、Android录Gif、Android录视频
  • 原文地址:https://www.cnblogs.com/dddyyy/p/9965836.html
Copyright © 2011-2022 走看看