【JAVA】ReentrantLock使用方法

                                                   ReentrantLock学习

1、基本的使用,synchronized对象锁:

测试1:

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();
    }
}
public class MyThread extends Thread {
    private MyService service;
    public MyThread(MyService service){
        this.service=service;
    }
    @Override
    public void run(){
        service.testMethod();
    }
}
public class test {
    public static void main(String args[]){
        MyService service=new MyService();
        MyThread a1=new MyThread(service);
        MyThread a2=new MyThread(service);
        MyThread a3=new MyThread(service);
        MyThread a4=new MyThread(service);
        MyThread a5=new MyThread(service);

        a1.start();
        a2.start();
        a3.start();
        a4.start();
        a5.start();
    }
}

运行输出:

ThreadName=Thread-0 1
ThreadName=Thread-0 2
ThreadName=Thread-0 3
ThreadName=Thread-0 4
ThreadName=Thread-0 5
ThreadName=Thread-1 1
ThreadName=Thread-1 2
ThreadName=Thread-1 3
ThreadName=Thread-1 4
ThreadName=Thread-1 5
ThreadName=Thread-2 1
ThreadName=Thread-2 2
ThreadName=Thread-2 3
ThreadName=Thread-2 4
ThreadName=Thread-2 5
ThreadName=Thread-4 1
ThreadName=Thread-4 2
ThreadName=Thread-4 3
ThreadName=Thread-4 4
ThreadName=Thread-4 5
ThreadName=Thread-3 1
ThreadName=Thread-3 2
ThreadName=Thread-3 3
ThreadName=Thread-3 4
ThreadName=Thread-3 5

Process finished with exit code 0

测试2:

public class MyService {
    private Lock lock=new ReentrantLock();
    public void methodA(){
        try{
            lock.lock();
            System.out.println("methodA begin ThreadName="+Thread.currentThread()
            +" time="+System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println("methodA end ThreadName="+Thread.currentThread()
                    +" time="+System.currentTimeMillis());
        }catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void methodB(){
        try{
            lock.lock();
            System.out.println("methodB begin ThreadName="+Thread.currentThread()
                    +" time="+System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println("methodB end ThreadName="+Thread.currentThread()
                    +" time="+System.currentTimeMillis());
        }catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}


public class ThreadA extends Thread {
    private MyService service;
    public ThreadA(MyService service){
        super();
        this.service=service;
    }
    @Override
    public void run(){
        service.methodA();
    }
}

public class ThreadAA extends Thread {
    private MyService service;
    public ThreadAA(MyService service){
        super();
        this.service=service;
    }
    @Override
    public void run(){
        service.methodA();
    }
}

public class ThreadB extends Thread {
    private MyService service;
    public ThreadB(MyService service){
        super();
        this.service=service;
    }
    @Override
    public void run(){
        service.methodB();
    }
}

public class ThreadBB extends Thread {
    private MyService service;
    public ThreadBB(MyService service){
        super();
        this.service=service;
    }
    @Override
    public void run(){
        service.methodB();
    }
}

public class test {
    public static void main(String args[]){
        MyService service=new MyService();
        ThreadA a=new ThreadA(service);
        a.setName("A");
        ThreadAA aa=new ThreadAA(service);
        aa.setName("AA");
        ThreadB b=new ThreadB(service);
        b.setName("B");
        ThreadBB bb=new ThreadBB(service);
        bb.setName("BB");

        a.start();
        aa.start();
        b.start();
        bb.start();


    }
}

结果:
methodA begin ThreadName=Thread[AA,5,main] time=1534741677491
methodA end ThreadName=Thread[AA,5,main] time=1534741682492
methodA begin ThreadName=Thread[A,5,main] time=1534741682492
methodA end ThreadName=Thread[A,5,main] time=1534741687493
methodB begin ThreadName=Thread[B,5,main] time=1534741687493
methodB end ThreadName=Thread[B,5,main] time=1534741692493
methodB begin ThreadName=Thread[BB,5,main] time=1534741692493
methodB end ThreadName=Thread[BB,5,main] time=1534741697493

通过两测试可以发现,lock可以实现与synchronized一样的效果,那么lock与reentrantlock的差异在那里呢,我们继续看:

要注意synchronized同步,假如发生异常,JVM是可以帮我们自动释放锁的,但是lock不可以,我们只能手动释放锁,即使发生异常,jvm也不会自动释放锁

首先我们知道synchronized与wait()和notify()/notifyAll()方法结合可以实现等待通知模式,Reentrantlock可以实现同样的宫鞥你,在synchronized当中,被通知的线程是由JVM随机选择,但是lock结合condition可以实现选择性通知。

注意在condition.await()方法调用之前,必须先lock.lock()获得锁。

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时间为"+System.currentTimeMillis()
                    +"ThreadName="+Thread.currentThread().getName());
            conditionA.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());
            conditionB.await();
            System.out.println("end awaitB 时间为"+System.currentTimeMillis()
                    +"ThreadName"+Thread.currentThread().getName());

        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void signalAll_A(){
        try {
            lock.lock();
            System.out.println("signalAll_A时间为"+System.currentTimeMillis()
                    +"ThreadName"+ Thread.currentThread().getName());
            conditionA.signalAll();
        }finally {
            lock.unlock();
        }
    }
    public void signalAll_B(){
        try {
            lock.lock();
            System.out.println("signalAll_B时间为"+System.currentTimeMillis()
                    +"ThreadName"+ Thread.currentThread().getName());
            conditionB.signalAll();
        }finally {
            lock.unlock();
        }
    }
}


public class ThreadA extends Thread {
    private MyService service;
    public ThreadA(MyService service){
        super();
        this.service=service;
    }
    @Override
    public void run(){
        service.awaitA();
    }

}


public class ThreadB extends Thread {
    private MyService service;
    public ThreadB(MyService service){
        super();
        this.service=service;
    }
    @Override
    public void run(){
        service.awaitB();
    }
}


public class test {
    public static void main(String args[]){
        MyService service=new MyService();
        ThreadA a=new ThreadA(service);
        a.setName("A");

        ThreadB b=new ThreadB(service);
        b.setName("B");

        a.start();
        b.start();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        service.signalAll_A();


    }
}

输出:

begin awaitA时间为1534744090922ThreadName=A
begin awaitB时间为1534744090922ThreadName=B
signalAll_A时间为1534744093922ThreadNamemain
end awaitA 时间为1534744093922ThreadNameA

可以看到只有A被唤醒

synchronized的join()方法是为了让别的线程执行完在执行下面的语句

ThreadA a=new ThreadA();
a.start();
a.join();
//希望a执行完之后再执行语句
...........

join(long)是设置等待的时间

join(long)与sleep(long)的区别,join(long)在等待的时候释放锁,而sleep不会。

InheritableThreadLocal可以让子线程从父线程中取得值。

继承InheritableThreadLocal重写intialValue()方法

继承InheritableThreadLocal重写intialValue()与childValue()方法

ReentrantReadWriteLock的使用:读读共享,写写互斥,读写互斥

自旋锁也叫不可重入锁

//可重入锁的基本原理:
public class Lock{
    boolean isLocked = false;
    Thread  lockedBy = null; //记录已经获得锁的线程
    int lockedCount = 0;//记录加锁数量
    public synchronized void lock() throws InterruptedException{
        Thread callingThread = Thread.currentThread();
        while(isLocked && lockedBy != callingThread){
        //如果被锁并且当前线程是不是获得锁的线程,那么等待
            wait();
        }
        isLocked = true;
        lockedCount++;
        lockedBy = callingThread;
    }
    public synchronized void unlock(){
        if(Thread.curentThread() == this.lockedBy){
            //如果当前线程是之前获得锁的线程
            lockedCount--;
            if(lockedCount == 0){
                isLocked = false;
                notify();
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Awille/article/details/81869380