Lock锁

开始我比较喜欢使用synchronize关键字来实现线程的同步机制,因为他的使用方法很简单,不用考录很多的细节,对于初级程序猿来说,要求更低,

现在来介绍我刚学到的另外一种,通过Lock 锁来实现同步的方法,

Lock锁优点:能够使程序并发更加高效

    缺点:对程序猿的要求更高

Lock中的方法

public interface Lock {
    void lock();
    void lockInterruptibly() throws InterruptedException;
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    void unlock();
    Condition newCondition();
}


从Lock源码中可以看出,它是一个接口

  1)lock():如果能获取锁就返回,如果不能获取,则一直等待获取锁

  2)lockinterruptidly():支持线程中断,如果线程中断,则默认他不会去竞争,这个相对于同步代码块和同步方法而言,可扩展性大了很多

  3)trylock():如果能获取锁就立刻返回true 否则返回false

  4)trylock(ling time,TimeUnit unit)如果能获取锁则返回true  如果有一下两种情况,则返回false

      线程被中断了

      时间到了

  5)unlock()释放一个锁

  6)Condition newCondition()引入 condition有两个方法意图

    a.对一个共享资源有读和写的能力,如果读线程或写线程获取了Lock的权力,即有能力进入,但是如果里面没有内容,读也没有用,如果空间已满了,写也写不了,所以还得有条件去判断一下,是不是线程要等待了;

    b.提供一种多线程之间的通信机制,类似wait()和nofity()的原理。

锁的相关概念介绍

  1.可重入锁

    也叫递归锁,指同一线程外层函数获得该锁以后,内层递归函数仍有获取该锁的代码,但不受影响,

    在Java环境下,ReetrantLock和synchronize都是可重入锁,最大的作用是避免死锁  

lass MyClass {
    public synchronized void method1() {
        method2();
    }

    public synchronized void method2() {

    }
}

    在一个线程获得method1方法的锁后,进入method1,同样被synchronized修饰的method2方法就不需要再次去获取锁了。因为synchronized具有可重入性,所以进入直接运行

  2.可中断锁

    在Java中,synchronized就不是可中断锁,而Lock是可中断锁,这也是我们需要Lock实现同步的重要原因。

    如果某一线程A正在执行锁中的代码,另一线程B正在等待获取该锁,可能由于等待时间过长,线程B不想等待了,想先处理其他事情,我们可以让它中断自己或者在别的线程中中断它,这种就是可中断锁。

    在前面Lock的接口方法lockInterruptibly()的用法时已经体现了Lock的可中断性。

  3.公平锁  

    公平锁即尽量以请求锁的顺序来获取锁。比如同是有多个线程在等待一个锁,当这个锁被释放时,等待时间最久的线程(最先请求的线程)会获得该所,这种就是公平锁。

    非公平锁即无法保证锁的获取是按照请求锁的顺序进行的。这样就可能导致某个或者一些线程永远获取不到锁。

    在Java中,synchronized就是非公平锁,它无法保证等待的线程获取锁的顺序。

    而对于ReentrantLock和ReentrantReadWriteLock,它默认情况下是非公平锁,但是可以设置为公平锁。

 下附老师的我爱你程序源码

package com.cmy.Lock.demo3;
 import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 /**
 *  lock实现案例:线程A 线程B 线程C 打印 10次 '我爱你'
 *
 *  案例思路:使用一个ReentranLock 对象
 *          2个Condition对象 和synchronize(){}+wait()+notify()大致相仿
 */
public class LockConditionDemoWord implements Runnable{
    // 打印次数
    private static final int PRINT_COUNT = 10;
    // 打印锁
    private final ReentrantLock reentrantLock;
    // 本线程打印所需的condition
    private final Condition thisCondtion;
    // 下一个线程打印所需要的condition
    private final Condition nextCondtion;
    // 打印字符
    private final String printChar;
     public LockConditionDemoWord(ReentrantLock reentrantLock, Condition thisCondtion, Condition nextCondition,
                         String printChar) {
        this.reentrantLock = reentrantLock;
        this.nextCondtion = nextCondition;
        this.thisCondtion = thisCondtion;
        this.printChar = printChar;
    }
     @Override
    public void run() {
        // 获取打印锁 进入临界区
        reentrantLock.lock();
        try {
            // 连续打印PRINT_COUNT次
            for (int i = 0; i < PRINT_COUNT; i++) {
                //打印字符
                System.out.print(printChar);
                // 使用nextCondition唤醒下一个线程
                // 因为只有一个线程在等待,所以signal或者signalAll都可以
                nextCondtion.signal();
                // 不是最后一次则通过thisCondtion等待被唤醒
                // 必须要加判断,不然虽然能够打印10次,但10次后就会直接死锁
                if (i < PRINT_COUNT - 1) {
                    try {
                        // 本线程让出锁并等待唤醒
                        thisCondtion.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
             }
        } finally {
            // 释放打印锁
            reentrantLock.unlock();
        }
    }
     public static void main(String[] args) throws InterruptedException {
        // 写锁
        ReentrantLock lock = new ReentrantLock();
        // 打印a线程的condition
        Condition conditionA = lock.newCondition();
        // 打印b线程的condition
        Condition conditionB = lock.newCondition();
        // 打印c线程的condition
        Condition conditionC = lock.newCondition();
        // 实例化A线程
        Thread printerA = new Thread(new LockConditionDemoWord(lock, conditionA, conditionB, ""));
        // 实例化B线程
        Thread printerB = new Thread(new LockConditionDemoWord(lock, conditionB, conditionC, ""));
        // 实例化C线程
        Thread printerC = new Thread(new LockConditionDemoWord(lock, conditionC, conditionA, ""));
        // 依次开始A B C线程
        printerA.start();
        Thread.sleep(100);
        printerB.start();
        Thread.sleep(100);
        printerC.start();
    }
} 

 

posted @ 2018-10-09 08:49  米佳5714  阅读(133)  评论(0编辑  收藏  举报