Lock对象的使用

使用Lock对象实现同步效果,Lock对象在功能上比synchronized 更加丰富,着重要掌握 ReentrantLock 类和 ReentrantReadWriteLock 类的使用

ReentrantLock 类

使用ReentrantLock 实现同步

调用ReentrantLock 对象的lock方法获取锁,调用unlock 方法释放锁,这两个方法成对使用,要想实现代码同步只需把代码放在lock和unlock之间即可

package P299;

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

public class MyService {
    private Lock lock=new ReentrantLock();

    public void testMethod(){
        lock.lock();
        for (int i = 0; i < 5; i++) {
            System.out.println("ThreadName="+Thread.currentThread().getName()+(" "+(i+1)));
        }
        lock.unlock();
    }
}

package P299;

public class MyThread extends Thread {
    private MyService myService;

    public MyThread(MyService myService){
        this.myService=myService;
    }

    @Override
    public void run() {
        myService.testMethod();
    }
}

package P299;

public class Test {
    public static void main(String[] args) {
        MyService myService = new MyService();
        MyThread myThread1 = new MyThread(myService);
        MyThread myThread2 = new MyThread(myService);
        MyThread myThread3 = new MyThread(myService);

        myThread1.start();
        myThread2.start();
        myThread3.start();

    }
}

在这里插入图片描述

await 方法的使用

package P307;

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

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

    public void waitMethod(){
        try{
            lock.lock();
            System.out.println("A");
            condition.await();
            System.out.println("B");
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        finally {
            lock.unlock();
            System.out.println("锁被释放了");
        }
    }
}

package P307;

public class MyThreadA extends Thread {
    private MyService myService;
    public MyThreadA(MyService myService){
        this.myService=myService;
    }

    @Override
    public void run() {
        myService.waitMethod();
    }
}

在这里插入图片描述

await signal 实现等待通知机制

package P308;

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

public class MyService {
    private ReentrantLock lock=new ReentrantLock();
    private 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();
        }finally {
            lock.unlock();
        }
    }

}

package P308;


import java.net.ServerSocket;

public class ThreadA extends Thread {
    private MyService myService=new MyService();
    public ThreadA(MyService myService){
        this.myService=myService;
    }

    @Override
    public void run() {
        myService.await();
    }
}

package P308;

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

在这里插入图片描述

通知全部线程

package P312;

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

public class MyService {
    private Lock lock=new ReentrantLock();
    private Condition condition=lock.newCondition();

    public void awaitA(){
        try {
            lock.lock();
            System.out.println("begin awaitA时间为"+System.currentTimeMillis()+"  ThreadName="+Thread.currentThread().getName());
            condition.await();
            System.out.println("end awaitA时间为"+System.currentTimeMillis()+"  ThreadName="+Thread.currentThread().getName());
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        finally {
            lock.unlock();
        }
    }

    public void awaitB(){
        try {
            lock.lock();
            System.out.println("begin awaitB时间为"+System.currentTimeMillis()+"  ThreadName="+Thread.currentThread().getName());
            condition.await();
            System.out.println("end awaitB时间为"+System.currentTimeMillis()+"  ThreadName="+Thread.currentThread().getName());
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void signalAll(){
        try {
            lock.lock();
            System.out.println("signalAll时间为"+System.currentTimeMillis()+"  ThreadName="+Thread.currentThread().getName());
            condition.signalAll();
        }finally {
            lock.unlock();
        }
    }
}

在这里插入图片描述

通知部分线程

package P315;

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

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

    public void awaitA(){
        try {
            lock.lock();
            System.out.println("begin awaitA time="+System.currentTimeMillis()+"  ThreadName="+ Thread.currentThread().getName());
            conditionA.await();
            System.out.println("end awaitA time="+System.currentTimeMillis()+"  ThreadName="+ Thread.currentThread().getName());
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void awaitB(){
        try {
            lock.lock();
            System.out.println("begin awaitB time="+System.currentTimeMillis()+"  ThreadName="+ Thread.currentThread().getName());
            conditionB.await();
            System.out.println("end awaitB time="+System.currentTimeMillis()+"  ThreadName="+ Thread.currentThread().getName());
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void signalA(){
        try {
            lock.lock();
            System.out.println("signalA time="+System.currentTimeMillis()+"  ThreadName="+ Thread.currentThread().getName());
            conditionA.signalAll();
        }finally {
            lock.unlock();
        }
    }

    public void signalB(){
        try {
            lock.lock();
            System.out.println("signalB time="+System.currentTimeMillis()+"  ThreadName="+ Thread.currentThread().getName());
        }finally {
            lock.unlock();
        }
    }
}

package P315;


public class ThreadA extends Thread {
    private MyService myService;
    public ThreadA(MyService myService){
        this.myService=myService;
    }

    @Override
    public void run() {
        myService.awaitA();
    }
}

package P315;

public class ThreadB extends Thread {
    private MyService myService;
    public ThreadB(MyService myService){
        this.myService=myService;
    }

    @Override
    public void run() {
        myService.awaitB();
    }
}

package P315;

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

在这里插入图片描述

生产者、消费者一对一交替输出

package P317;

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

public class MyService {
    private ReentrantLock lock=new ReentrantLock();
    private Condition condition=lock.newCondition();
    private boolean hasValue=false;
    public void set(){
        try {
            lock.lock();
            if(hasValue==true){
                condition.await();
            }
            System.out.println("A");
            hasValue=true;
            condition.signal();
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void get(){
        try {
            lock.lock();
            if(hasValue==false){
                condition.await();
            }
            System.out.println("B");
            hasValue=false;
            condition.signal();
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

package P317;

public class MyThreadA extends Thread {
    private MyService myService;
    public MyThreadA(MyService myService){
        this.myService=myService;
    }

    @Override
    public void run() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            myService.set();
        }
    }
}

package P317;


public class MyThreadB extends Thread {
    private MyService myService;
    public MyThreadB(MyService myService){
        this.myService= myService;
    }

    @Override
    public void run() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            myService.get();
        }
    }
}

package P317;

public class Run {
    public static void main(String[] args) {
        MyService myService = new MyService();
        MyThreadA myThreadA = new MyThreadA(myService);
        MyThreadB myThreadB = new MyThreadB(myService);

        myThreadA.start();
        myThreadB.start();
    }
}

在这里插入图片描述

生产者、消费则多对多交替输出

package P317;

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

public class MyService {
    private ReentrantLock lock=new ReentrantLock();
    private Condition condition=lock.newCondition();
    private boolean hasValue=false;
    public void set(){
        try {
            lock.lock();
            while (hasValue==true){
                condition.await();
            }
            System.out.println("A"+"----"+Thread.currentThread().getName());
            Thread.sleep(100);
            hasValue=true;
            condition.signalAll();
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void get(){
        try {
            lock.lock();
            while (hasValue==false){
                condition.await();
            }
            System.out.println("B"+"----"+Thread.currentThread().getName());
            Thread.sleep(100);
            hasValue=false;
            condition.signalAll();
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

package P317;

public class MyThreadA extends Thread {
    private MyService myService;
    public MyThreadA(MyService myService){
        this.myService=myService;
    }

    @Override
    public void run() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            myService.set();
        }
    }
}

package P317;


public class MyThreadB extends Thread {
    private MyService myService;
    public MyThreadB(MyService myService){
        this.myService= myService;
    }

    @Override
    public void run() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            myService.get();
        }
    }
}

package P317;

public class Run {
    public static void main(String[] args) {
        MyService myService = new MyService();
        for (int i = 0; i < 5; i++) {
            MyThreadA myThreadA = new MyThreadA(myService);
            MyThreadB myThreadB = new MyThreadB(myService);
            myThreadA.start();
            myThreadB.start();
        }
    }
}

在这里插入图片描述
注意:使用signal 可能会出现假死,使用signalAll则可以避免;while

公平锁和非公平锁

公平锁:采用先到先得的策略,每次获取锁之前会检查队列里有没有排队等待的线程,没有才会去获取锁,否则就将当前线程追加到队列中

package P323;

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

public class MyService {
    public Lock lock;
    public MyService(boolean fair){
        lock=new ReentrantLock(fair);
    }
    public void testMethod(){
        try {
            lock.lock();
            System.out.println("testMethod "+Thread.currentThread().getName());
            Thread.sleep(500);
            lock.unlock();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

package P323;

public class MyThread extends Thread {
    private MyService myService;
    public MyThread(MyService myService){
        this.myService=myService;
    }

    @Override
    public void run() {
        myService.testMethod();
    }
}

package P323;

public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyService myService = new MyService(true);
        MyThread[] myThreads = new MyThread[10];
        MyThread[] myThreads1 = new MyThread[10];
        for (int i = 0; i < myThreads.length; i++) {
            myThreads[i]=new MyThread(myService);
            myThreads[i].setName("A++++"+(i+1));
        }
        for (int i = 0; i <myThreads.length; i++) {
            myThreads[i].start();
        }
        for (int i = 0; i < myThreads1.length; i++) {
            myThreads1[i]=new MyThread(myService);
            myThreads1[i].setName("B++++"+(i+1));
        }
        Thread.sleep(500);
        for (int i = 0; i < myThreads1.length; i++) {
            myThreads1[i].start();
        }
    }
}

在这里插入图片描述
非公平锁:采用“有机会插队”的策略,一个线程获取锁之前要先去尝试获取锁而不是在队列中等待,如果锁获取成功,则说明虽然线程是后启动的,但是先获取了锁。如果没有获取锁成功,那么才将自身追加到队列中等待
多次运行可能出现后启动的线程先抢到锁

常见方法

public int getHoldCount()

当前线程保持锁的个数,即调用lock方法的次数

public final int getQueueLength()

返回正等待获取此锁的线程估计数

使用ReentrantReadWriteLock类

ReentrantLock类具有完全互斥排他的效果,同一时间只有一个线程执行ReentrantLock.lock()方法后面的任务,这样做虽然保证了同时写实例变量的线程安全性,但是效率非常低下。
使用ReentrantReadWriteLock类可以进行读操作时不需要同步执行,提升速度,加快效率
读相关的锁也称为共享锁,写相关的锁也成为排它锁
读锁之间不互斥,读锁和写锁互斥,写锁和写锁也互斥

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值