Lock

Posted rookiejw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lock相关的知识,希望对你有一定的参考价值。

今天看了 Lock,最大的感觉就是 ReentrantLock 类有很多方法可以使用

为什么提出Lock?

Lock 是 Java1.5 后提出来的,之前有 synchronized 关键字来控制同步。那么为什么要提出Lock呢?肯定是 synchronized 有缺陷所以需要完善。

synchronized 使用在方法上加上关键字或使用 synchronized 同步块。

问题一: 读者写者问题?读者与读者不互斥,读者写者互斥,写者写者互斥。

如果用 synchronized 实现,是不是读者读者之间会互斥,只能一个进行读。而用Lock实现就比较快 ReentrantReadWriteLock 类(后面会写)。

问题二:如果你想知道某个线程有没有获取到了锁?synchronized不行而Lock行。

问题三:在多线程中常常会出现一个线程拿到了锁而其它线程一直在等锁释放,如果这个线程在等待IO或其他原因被阻塞了。现在有个需求如果有些线程等了10秒就不想等了放弃了,使用 synchronized 怕事实现不了。需求二 先尝试下能不能获取锁,如果获取不到就算了。


来来来写个程序看看

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
public static void main(String[] args) {
    MyServiceLock serviceLock = new MyServiceLock();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            serviceLock.myServiceLockMethod();
        }
    };
    Thread[] threads = new Thread[5];
    for (int i = 0; i < threads.length; i++) {
        threads[i] = new Thread(runnable);
    }
    for (int i = 0; i < threads.length; i++) {
        threads[i].start();
    }
}
}

class MyServiceLock {
private Lock lock = new ReentrantLock();

public void myServiceLockMethod() {
    try {
        lock.lock();
        System.out.println(Thread.currentThread().getName() + "  myServiceLockMethod");
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }

}
}

技术分享图片

Lock 与 synchronized 相比 Lock 需要手动释放锁调用 unlock()方法。如果你忘记写了那么....其它线程堵塞吧。


Lock源码

技术分享图片

Lock是一个接口。

void lock():获得锁。 如果锁不可用,则当前线程将被禁用以进行线程调度,并处于休眠状态,直到获取锁。

void lockInterruptibly():如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。

boolean tryLock():调用时如果锁未被其它线程获取,就能获取锁

boolean tryLock(long,TimeUnit):如果锁定在给定等待时间内没有被另外一个线程保持,且当前线程未被中断,则获取该锁定。

void unlock():释放锁。

Condition newCondition():返回一个新Condition绑定到该实例Lock实例。

已经实现的类:

技术分享图片


ReentrantLock

技术分享图片

两个构造器默认情况是非公平锁

/**
 * Creates an instance of {@code ReentrantLock}.
 * This is equivalent to using {@code ReentrantLock(false)}.
 */
public ReentrantLock() {
    sync = new NonfairSync();
}

/**
 * Creates an instance of {@code ReentrantLock} with the
 * given fairness policy.
 *
 * @param fair {@code true} if this lock should use a fair ordering policy
 */
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

什么是公平锁什么事非公平锁?

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class RunFair {
public static void main(String[] args) {
    //可传入参数使用公平锁和非公平锁
    Service service=new Service(false);
    Runnable runnable=new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+"进入了run 方法###");
            service.serviceMethod();
        }
    };
    Thread[] threads=new Thread[10];
    for (int i = 0; i < threads.length; i++) {
        threads[i]=new Thread(runnable);
    }
    for (int i = 0; i < threads.length; i++) {
        threads[i].start();
    }
}
}

class Service{
private boolean isFair;
private Lock lock=new ReentrantLock();
public Service(boolean isFair){
    this.isFair=isFair;
}

public void serviceMethod(){
    try{
        lock.lock();
        System.out.println(Thread.currentThread().getName()+"运行了serviceMethod");
    }finally {
        lock.unlock();
    }
}
}

技术分享图片

改成安全锁后

Service service=new Service(true);

技术分享图片

对比这两个结果可发现:公平锁按线程加锁的顺序来分配的,FIFO先进先出顺序。而非公平锁是一种抢占机制是随机获取锁的。

synchronized也是非公平锁。

 //在Service类中添加一个synchronized修饰的方法
 public synchronized void serviceMethodSyn(){
    System.out.println(Thread.currentThread().getName()+"运行了serviceMethodSyn");
}

Runnable runnable=new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+"进入了run 方法###");
            service.serviceMethodSyn();
        }
    };

技术分享图片


void lockInterruptibly()

作用:如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
public static void main(String[] args) {
    MyServiceLock myServiceLock=new MyServiceLock();
    Runnable runnable=new Runnable() {
        @Override
        public void run() {
            myServiceLock.myServiceLockMethod();
        }
    };
    Thread threadOne=new Thread(runnable);
    Thread threadTwo=new Thread(runnable);
    threadOne.start();
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    threadTwo.start();
    threadTwo.interrupt();
    System.out.println(threadTwo.isInterrupted());

}
}

class MyServiceLock {
private Lock lock = new ReentrantLock();

public void myServiceLockMethod() {
    try {
        lock.lockInterruptibly();
        System.out.println(Thread.currentThread().getName() + "  myServiceLockMethod");
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }

}
}

技术分享图片


tryLock()、tryLock(long,TimeUnit)

tryLock作用:尝试去获取锁定,如果锁定未被一个线程保持的情况下,就可以获取锁定。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
public static void main(String[] args) {
    MyServiceLock myServiceLock = new MyServiceLock();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            myServiceLock.myServiceLockMethod();
        }
    };
    Thread threadOne=new Thread(runnable);
    Thread threadTwo=new Thread(runnable);
    threadOne.start();
    threadTwo.start();

}
}

class MyServiceLock {
private Lock lock = new ReentrantLock();

public void myServiceLockMethod() {
        if(lock.tryLock()) {
            System.out.println(Thread.currentThread().getName()+"获取了锁");
            lock.unlock();
        }else {
            System.out.println(Thread.currentThread().getName()+"获取锁失败");
        }
}
}

技术分享图片

tryLock(long timeout,TimeUnit unit) 作用:在给定时间内该线程如果没有被中断且锁定没有被另外一个线程保持,则获取该锁定。

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
public static void main(String[] args) {
    MyServiceLock myServiceLock = new MyServiceLock();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            myServiceLock.waitMethod();
        }
    };
    Thread threadOne=new Thread(runnable);
    Thread threadTwo=new Thread(runnable);
    threadOne.start();
    threadTwo.start();

}
}

class MyServiceLock {
private ReentrantLock lock = new ReentrantLock();
public void waitMethod(){
    try {
        if (lock.tryLock(3, TimeUnit.SECONDS)){
            System.out.println(Thread.currentThread().getName()+"获取了锁"+" "+System.currentTimeMillis());
            Thread.sleep(4000);
        }else{
            System.out.println(Thread.currentThread().getName()+"没有获取到锁");
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }finally {
        if(lock.isHeldByCurrentThread()){
            System.out.println(Thread.currentThread().getName()+"释放了锁"+System.currentTimeMillis());
            lock.unlock();
        }
    }
}
}

技术分享图片

//加句
threadTwo.interrupt();

技术分享图片


newCondition()

返回 Condition 实例支持相同的用途为做 Object 种监视器方法( wait , notify和notifyAll 与使用时)内置监视器锁定。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
public static void main(String[] args) {
    MyServiceLock myServiceLock = new MyServiceLock();
    ThreadWaitA threadWaitA = new ThreadWaitA(myServiceLock);
    ThreadWaitB threadWaitB = new ThreadWaitB(myServiceLock);
    ThreadSignalA threadSignalA = new ThreadSignalA(myServiceLock);
    ThreadSignalB threadSignalB = new ThreadSignalB(myServiceLock);
    threadWaitA.start();
    threadWaitB.start();
    threadSignalA.start();
    threadSignalB.start();
}
}

class MyServiceLock {
private Lock lock = new ReentrantLock();
private Condition conditionA = lock.newCondition();
private Condition conditionB = lock.newCondition();

public void waitMethodA() {
    try {
        lock.lock();
        System.out.println(Thread.currentThread().getName() + "获取了锁" + System.currentTimeMillis());
        conditionA.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        System.out.println(Thread.currentThread().getName() + "释放了锁" + System.currentTimeMillis());
        lock.unlock();
    }
}

public void waitMethodB() {
    try {
        lock.lock();
        System.out.println(Thread.currentThread().getName() + "获取了锁" + System.currentTimeMillis());
        conditionB.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        System.out.println(Thread.currentThread().getName() + "释放了锁" + System.currentTimeMillis());
        lock.unlock();
    }
}

public void singnalA() {
    try {
        lock.lock();
        System.out.println(Thread.currentThread().getName() + " 唤醒所有ConditionA: await");
        conditionA.signalAll();
    } finally {
        lock.unlock();
    }
}

public void singnalB() {
    try {
        lock.lock();
        System.out.println(Thread.currentThread().getName() + " 唤醒所有ConditionB: await");
        conditionB.signalAll();
    } finally {
        lock.unlock();
    }
}
}

class ThreadWaitA extends Thread {
private MyServiceLock myServiceLock;

public ThreadWaitA(MyServiceLock myServiceLock) {
    this.myServiceLock = myServiceLock;
}

@Override
public void run() {
    myServiceLock.waitMethodA();
}
}

class ThreadWaitB extends Thread {
private MyServiceLock myServiceLock;

public ThreadWaitB(MyServiceLock myServiceLock) {
    this.myServiceLock = myServiceLock;
}

@Override
public void run() {
    myServiceLock.waitMethodB();
}
}

class ThreadSignalA extends Thread {
private MyServiceLock myServiceLock;

public ThreadSignalA(MyServiceLock myServiceLock) {
    this.myServiceLock = myServiceLock;
}

@Override
public void run() {
    myServiceLock.singnalA();
}
}

class ThreadSignalB extends Thread {
private MyServiceLock myServiceLock;

public ThreadSignalB(MyServiceLock myServiceLock) {
    this.myServiceLock = myServiceLock;
}

@Override
public void run() {
    myServiceLock.singnalB();
}
}

技术分享图片


getHoldCount()

getHoldCount() 作用:查询当前线程保持锁定的个数,也就是调用 lock() 方法的次数。

import java.util.concurrent.locks.ReentrantLock;

public class Main {
public static void main(String[] args) {
    MyService myService=new MyService();
    Runnable runnable=new Runnable() {
        @Override
        public void run() {
            myService.myServiceMethodA();
        }
    };
    Thread threadOne=new Thread(runnable);
    Thread threadTwo=new Thread(runnable);
    threadOne.start();
    threadTwo.start();

}
}

class MyService{
private ReentrantLock reentrantLock=new ReentrantLock();

public void myServiceMethodA(){
    try {
        reentrantLock.lock();
        System.out.println(Thread.currentThread().getName()+"获取了锁");
        System.out.println(reentrantLock.getHoldCount());
        myServiceMethodB();
    }finally {
        System.out.println(Thread.currentThread().getName()+"释放了锁");
        reentrantLock.unlock();
    }
}

public void myServiceMethodB(){
    try {
        reentrantLock.lock();
        System.out.println(reentrantLock.getHoldCount());
    }finally {
        System.out.println(Thread.currentThread().getName()+"释放了锁");
        reentrantLock.unlock();
    }
}
}

isHeldByCurrentThread()

isHeldByCurrentThread() 作用:查询此锁是否由当前线程持有。

import java.util.concurrent.locks.ReentrantLock;

public class Main {
public static void main(String[] args) {
    MyService myService=new MyService();
    Runnable runnable=new Runnable() {
        @Override
        public void run() {
            myService.myServiceMethodA();
        }
    };
    Thread threadOne=new Thread(runnable);
    threadOne.start();

}
}

class MyService{
private ReentrantLock reentrantLock=new ReentrantLock();

public void myServiceMethodA(){
    try {
        reentrantLock.lock();
        System.out.println(Thread.currentThread().getName()+" "+reentrantLock.isHeldByCurrentThread());
    }finally {
        reentrantLock.unlock();
        System.out.println(Thread.currentThread().getName()+" "+reentrantLock.isHeldByCurrentThread());
    }
}
}

技术分享图片

isLocked()

isLocked() 作用:查询此锁是否由任何线程持有。 该方法设计用于监视系统状态,不用于同步控制。

import java.util.concurrent.locks.ReentrantLock;

public class Main {
public static void main(String[] args) {
    MyService myService=new MyService();
    Runnable runnable=new Runnable() {
        @Override
        public void run() {
            myService.myServiceMethodA();
        }
    };
    Thread threadOne=new Thread(runnable);
    threadOne.start();

}
}

class MyService{
private ReentrantLock reentrantLock=new ReentrantLock();

public void myServiceMethodA(){
    try {
        System.out.println(reentrantLock.isLocked());
        reentrantLock.lock();
        System.out.println(reentrantLock.isLocked());
    }finally {
        reentrantLock.unlock();
        System.out.println(reentrantLock.isLocked());
    }
}
}

技术分享图片


isFair()

isFair() 的作用:是否是公平锁

import java.util.concurrent.locks.ReentrantLock;

public class Main {
public static void main(String[] args) {
    MyService myService=new MyService();
    Runnable runnable=new Runnable() {
        @Override
        public void run() {
            myService.myServiceMethodA();
        }
    };
    Thread threadOne=new Thread(runnable);
    threadOne.start();

}
}

class MyService{
private ReentrantLock reentrantLock=new ReentrantLock();
private ReentrantLock reentrantLockTwo=new ReentrantLock(true);
public void myServiceMethodA(){
    System.out.println(reentrantLock.isFair());
    System.out.println(reentrantLockTwo.isFair());
}
}

技术分享图片


hasQueuedThreads()

hasQueuedThreads() 的作用:查询是否有线程正在等待获取此锁。 请注意,由于取消可能随时发生, true返回不保证任何其他线程将获得此锁。 该方法主要用于监视系统状态。
import java.util.concurrent.locks.ReentrantLock;

public class Main {
public static void main(String[] args) {
    MyService myService = new MyService();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            myService.myServiceMethodA();
        }
    };
    Thread threadOne = new Thread(runnable);
    Thread threadTwo = new Thread(runnable);
    threadOne.start();
    threadTwo.start();
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(myService.reentrantLock.hasQueuedThreads());

}
}

class MyService {
public ReentrantLock reentrantLock = new ReentrantLock();

public void myServiceMethodA() {
    try {
        reentrantLock.lock();
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }finally {
        reentrantLock.unlock();
    }
}
}

技术分享图片


hasQueuedThread(Thread thread)

hasQueuedThread(Thread thread) 作用:查询给定线程是否等待获取此锁。 请注意,因为取消可能随时发生, true返回并不能保证此线程将获得此锁。 该方法主要用于监视系统状态。

import java.util.concurrent.locks.ReentrantLock;

public class Main {
public static void main(String[] args) {
    MyService myService = new MyService();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            myService.myServiceMethodA();
        }
    };
    Thread threadOne = new Thread(runnable);
    Thread threadTwo = new Thread(runnable);
    threadOne.start();
    threadTwo.start();
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(myService.reentrantLock.hasQueuedThread(threadOne));
    System.out.println(myService.reentrantLock.hasQueuedThread(threadTwo));

}
}

class MyService {
public ReentrantLock reentrantLock = new ReentrantLock();

public void myServiceMethodA() {
    try {
        reentrantLock.lock();
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }finally {
        reentrantLock.unlock();
    }
}
}

技术分享图片


getQueueLength()

getQueueLength() 的作用:返回正等待获取此锁定的线程估计数。该值只是一个估计,因为线程数可能会在此方法遍历内部数据结构时动态更改。 该方法设计用于监视系统状态,不用于同步控制。

import java.util.concurrent.locks.ReentrantLock;

public class Main {
public static void main(String[] args) {
    MyService myService = new MyService();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            myService.myServiceMethodA();
        }
    };
    Thread[] threads=new Thread[10];
    for (int i = 0; i < threads.length; i++) {
        threads[i]=new Thread(runnable);
    }
    for (int i = 0; i < threads.length; i++) {
        threads[i].start();
    }
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(myService.reentrantLock.getQueueLength());

}
}

class MyService {
public ReentrantLock reentrantLock = new ReentrantLock();

public void myServiceMethodA() {
    try {
        reentrantLock.lock();
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }finally {
        reentrantLock.unlock();
    }
}
}

技术分享图片


getWaitQueueLength(Condition condition)

getWaitQueueLength(Condition condition) 的作用:返回与此锁相关联的给定条件等待的线程数的估计。 请注意,由于超时和中断可能在任何时间发生,估计仅作为实际服务员人数的上限。 该方法设计用于监视系统状态,不用于同步控制。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
public static void main(String[] args) {
    MyService myService = new MyService();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            myService.myServiceMethodA();
        }
    };
    Thread[] threads=new Thread[10];
    for (int i = 0; i < threads.length; i++) {
        threads[i]=new Thread(runnable);
    }
    for (int i = 0; i < threads.length; i++) {
        threads[i].start();
    }
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    myService.signalAll();

}
}

class MyService {
public ReentrantLock reentrantLock = new ReentrantLock();
public Condition condition=reentrantLock.newCondition();
public void myServiceMethodA() {
    try {
        reentrantLock.lock();
        condition.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }finally {
        reentrantLock.unlock();
    }
}

public void signalAll(){
    try {
        reentrantLock.lock();
        System.out.println(reentrantLock.getWaitQueueLength(condition));
        condition.signalAll();
    }finally {
        reentrantLock.unlock();
    }
}
}

技术分享图片


hasWaiters(Condition condition)

hasWaiters(Condition condition) 的作用:查询任何线程是否等待与此锁相关联的给定条件。 请注意,由于超时和中断可能会随时发生,所以true返回并不能保证将来的signal将唤醒任何线程。 该方法主要用于监视系统状态。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
public static void main(String[] args) {
    MyService myService = new MyService();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            myService.myServiceMethodA();
        }
    };
    Thread[] threads=new Thread[10];
    for (int i = 0; i < threads.length; i++) {
        threads[i]=new Thread(runnable);
    }
    for (int i = 0; i < threads.length; i++) {
        threads[i].start();
    }
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    myService.signalAll();

}
}

class MyService {
public ReentrantLock reentrantLock = new ReentrantLock();
public Condition condition=reentrantLock.newCondition();
public void myServiceMethodA() {
    try {
        reentrantLock.lock();
        condition.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }finally {
        reentrantLock.unlock();
    }
}

public void signalAll(){
    try {
        reentrantLock.lock();
        System.out.println(reentrantLock.hasWaiters(condition));
        condition.signalAll();
    }finally {
        reentrantLock.unlock();
    }
}
}

技术分享图片


awaitUninterruptibly()

awaitUninterruptibly() 的作用:与 await() 方法基本相同,但它不会在等待的过程中响应中断!

await():使当前线程等待,同时释放占有的锁;当线程被signal()或singnalAll()方法唤醒,或则该线程被中断时,线程跳出等待,与Object.wait()方法很相似。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
public static void main(String[] args) {
    MyService myService = new MyService();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            myService.myServiceMethodA();
        }
    };
    Thread thread=new Thread(runnable);
    thread.start();
    thread.interrupt();
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    myService.signalAll();

}
}

class MyService {
public ReentrantLock reentrantLock = new ReentrantLock();
public Condition condition=reentrantLock.newCondition();
public void myServiceMethodA() {
    try {
        reentrantLock.lock();
        System.out.println("wait begin");
        condition.awaitUninterruptibly();
        System.out.println("wait end");
//        } catch (InterruptedException e) {
//            e.printStackTrace();
    }finally {
        reentrantLock.unlock();
    }
}

public void signalAll(){
    try {
        reentrantLock.lock();
        condition.signalAll();
    }finally {
        reentrantLock.unlock();
    }
}
}

技术分享图片


awaitUntil(Date deadline)

awaitUntil(Date deadline) 作用: 等待deadline时间后释放,也可以在deadline时间内被唤醒。

import java.util.Calendar;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
public static void main(String[] args) {
    MyService myService = new MyService();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            myService.myServiceMethodA();
        }
    };
    Thread thread = new Thread(runnable);
    thread.start();


}
}

class MyService {
public ReentrantLock reentrantLock = new ReentrantLock();
public Condition condition = reentrantLock.newCondition();

public void myServiceMethodA() {
    try {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.SECOND, 10);
        reentrantLock.lock();
        System.out.println("wait begin " + System.currentTimeMillis());
        condition.awaitUntil(calendar.getTime());
        System.out.println("wait end " + System.currentTimeMillis());
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        reentrantLock.unlock();
    }
}
}

技术分享图片

import java.util.Calendar;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
public static void main(String[] args) {
    MyService myService = new MyService();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            myService.myServiceMethodA();
        }
    };
    Thread thread = new Thread(runnable);
    thread.start();
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    myService.signalAll();


}
}

class MyService {
public ReentrantLock reentrantLock = new ReentrantLock();
public Condition condition = reentrantLock.newCondition();

public void myServiceMethodA() {
    try {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.SECOND, 10);
        reentrantLock.lock();
        System.out.println("wait begin " + System.currentTimeMillis());
        condition.awaitUntil(calendar.getTime());
        System.out.println("wait end " + System.currentTimeMillis());
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        reentrantLock.unlock();
    }
}

public void signalAll() {
    try {
        reentrantLock.lock();
        condition.signalAll();
    } finally {
        reentrantLock.unlock();
    }
}
}

技术分享图片


ReentrantReadWriteLock类

ReentrantReadWriteLock类可以实现读者写者问题。

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Main {
public static void main(String[] args) {
    MyService myService = new MyService();
    Runnable runnableReader = new Runnable() {
        @Override
        public void run() {
            myService.read();
        }
    };
    Runnable runnableWriter = new Runnable() {
        @Override
        public void run() {
            myService.write();
        }
    };
    Thread[] threadRead = new Thread[3];
    for (int i = 0; i < threadRead.length; i++) {
        threadRead[i] = new Thread(runnableReader);
    }
    Thread[] threadWrite = new Thread[3];
    for (int i = 0; i < threadWrite.length; i++) {
        threadWrite[i] = new Thread(runnableWriter);
    }
    for (int i = 0; i < 3; i++) {
        threadRead[i].start();
        threadWrite[i].start();
    }


}
}

class MyService {
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

public void read() {
    try {
        lock.readLock().lock();
        System.out.println("获取锁 " + "读者" + Thread.currentThread().getName() + "  " + System.currentTimeMillis());
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.readLock().unlock();
    }
}

public void write() {
    try {
        lock.writeLock().lock();
        System.out.println("获取锁 " + "写者" + Thread.currentThread().getName() + "  " + System.currentTimeMillis());
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.writeLock().unlock();
    }
}
}

注释掉写者
// threadWrite[i].start();

技术分享图片

注释掉读者

//            threadRead[i].start();

技术分享图片

都不注释

技术分享图片


总结

类别 synchronized Lock
存在层次 Java的关键字,在jvm层面上 是一个接口, 实现类:ReentrantLock , ReentrantReadWriteLock.ReadLock , ReentrantReadWriteLock.WriteLock
锁类型 可重入、不可中断、非公平锁 可重入、可以判断、可是设置公平锁
锁状态 不能判断 可以判断
锁的释放 1、以获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm会让线程释放锁 在finally中必须释放锁,不然会堵塞
锁的获取 synchronized修饰方法或synchronized同步块,如果某个线程获取到锁其它线程需要等待 lock(),Lock有多个锁获取的方式,可以tryLock(),tryLock(long time, TimeUnit unit)
性能 少量同步 大量同步

参考https://blog.csdn.net/u012403290/article/details/64910926?locationNum=11&fps=1
Java多线程编程核心技术

才学疏浅,有什么问题请大家指出来。十分感谢!

以上是关于Lock的主要内容,如果未能解决你的问题,请参考以下文章

线程基础四 使用Monitor类锁定资源

Java多线程与并发库高级应用-工具类介绍

ReentrantReadWriteLock场景应用

并发技术12线程锁技术的使用

java并发线程锁技术的使用

Java多线程与并发库高级应用-工具类介绍