zoukankan      html  css  js  c++  java
  • Java基础教程:多线程基础——锁机制

    Java基础教程:多线程基础——锁机制

    显示锁

    ReentrantLock

      ReentrantLock是一种标准的互斥锁,每次只允许一个线程持有ReentrantLock。

      使用ReentrantLock来保护对象状态:

           Lock lock = new ReentrantLock();
           lock.lock();
           try {
               //更新对象状态
               //捕获异常,并在必要时恢复不变性条件
           }finally {
               lock.unlock();
           } 
    

      如果没有finally来释放Lock,相当于启动了一个定时炸弹。

    ReentrantReadWriteLock

      互斥锁是一种保守的枷锁策略,它虽然避免了“写/写”冲突,“写/读”冲突,但是同样也避免了“读/读”操作。在许多情况下,数据结构上的操作都是“读操作”。若放宽加锁需求,允许多个执行读操作的线程同时访问数据结构,那么将提高程序的性能

      我们引入读写锁,它允许一个资源可以被多个读操作访问,或者被一个写操作访问,但两者不能同时进行。也就是说当写操作进行时,所有读操作都进入阻塞状态,只有写操作完成后,读操作才能获取到最新状态,避免了脏读的发生

      在如下的代码中,我们使用读写锁封装一个Map,来使其线程安全。

    public class ReadWriteMap<K,V> {
        private final Map<K,V> map;
        private final ReadWriteLock lock = new ReentrantReadWriteLock();
        private final Lock r = lock.readLock();
        private final Lock w = lock.writeLock();
    
        public ReadWriteMap(Map<K,V> map){
            this.map = map;
        }
    
        public V put(K key,V value){
            w.lock();
            try {
                return map.put(key,value);
            } finally {
                w.unlock();
            }
        }
    
        public V get(Object key){
            r.lock();
            try {
                return map.get(key);
            } finally {
                r.unlock();
            }
        }
    }
    

      

     

    使用Condition实现等待/通知

      关键字Synchronized与wait、notify/All方法相结合可以实现等待/通知模式,类ReentrantLock同样可以实现相同的功能,但是需要借助Condition

      Condition类是JDK5出现的新技术,可以实现 多路通知的功能,也就是在一个Lock对象里可以创建多个Condition(即对象监视器)实例,线程对象可以注册在指定的Condition中,从而可以有选择性地进行线程通知,在调度线程上更加灵活。

      必须在Condition.await()方法调用之前调用Lock.lock()方法获得同步监视器

    MyService类

    public class MyService {
        private Lock lock  = new ReentrantLock();
        public Condition condition = lock.newCondition();
    
        public void await()
        {
            try {
                lock.lock();
                System.out.println("await的等待时间是"+System.currentTimeMillis());
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    
        public void signal()
        {
            try {
                lock.lock();
                System.out.println("signal的等待时间是"+System.currentTimeMillis());
                condition.signal();
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
    
        }
    }  

    ThreadA类

    public class ThreadA extends Thread {
        private MyService myService;
    
        public ThreadA(MyService myService) {
            this.myService = myService;
        }
    
        @Override
        public void run() {
            myService.await();
        }
    }  

    Main类

    public class Main {
        public static void main(String[] args) throws InterruptedException {
            MyService myService = new MyService();
            ThreadA threadA = new ThreadA(myService);
            threadA.start();
            Thread.sleep(3000);
            myService.signal();
        }
    }  

    多个Condition实现通知部分线程

    MyService类

    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class MySevice {
        private Lock lock = new ReentrantLock();
        public Condition conditionA = lock.newCondition();
        public Condition conditionB = lock.newCondition();
    
        public void awaitA()
        {
            try {
                lock.lock();
                System.out.println("awaitA的start时间是"+System.currentTimeMillis());
                conditionA.await();
                System.out.println("awaitA的end时间是"+System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    
        public void awaitB()
        {
            try {
                lock.lock();
                System.out.println("awaitB的start时间是"+System.currentTimeMillis());
                conditionB.await();
                System.out.println("awaitB的end时间是"+System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    
        public void signalA()
        {
            try {
                lock.lock();
                System.out.println("signalA的等待时间是"+System.currentTimeMillis());
                conditionA.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
    
        }
        public void signalB()
        {
            try {
                lock.lock();
                System.out.println("signalB的等待时间是"+System.currentTimeMillis());
                conditionB.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
    
        }
    }  

    ThreadA类

    public class ThreadA extends Thread {
        private MySevice myService;
    
        public ThreadA(MySevice myService) {
            this.myService = myService;
        }
    
        @Override
        public void run() {
            myService.awaitA();
        }
    }

    ThreadB类

    public class ThreadB extends Thread {
        private MySevice myService;
    
        public ThreadB(MySevice myService) {
            this.myService = myService;
        }
    
        @Override
        public void run() {
            myService.awaitB();
        }
    }
    

    Main类

    public class Main {
        public static void main(String[] args) throws InterruptedException {
            MySevice mySevice =new MySevice();
            ThreadA threadA = new ThreadA(mySevice);
            ThreadB threadB = new ThreadB(mySevice);
            threadA.start();
            threadB.start();
            Thread.sleep(3000);
            mySevice.signalA();
        }
    }
    

      

     

  • 相关阅读:
    关于IOS6屏幕旋转的问题
    学习备忘录
    关于多种手势问题
    关于 IOS中 绘制图形的问题
    爱的意义
    IOS支付SDK
    IOS开发特别备注
    ios相关教程
    iOS7光标问题
    收藏网站
  • 原文地址:https://www.cnblogs.com/MrSaver/p/9441109.html
Copyright © 2011-2022 走看看