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();
    }
}

  

 

 

posted @ 2018-08-08 10:06  子烁爱学习  阅读(361)  评论(0编辑  收藏  举报