ReentranLock

Reentrantlock

  • JDK1.5新增的ReentrantLock类,重入锁。

  • ReentrantLock是独占锁且可重入的

ReentrantLock和synchronized

相同点:

  1. ReentrantLock和synchronized都是独占锁,只允许线程互斥的访问临界区

  2. ReentrantLock和synchronized都是可重入的

不同点:

  1. synchronized加锁解锁的过程是隐式的,用户不用手动操作,优点是操作简单,但显得不够灵活;ReentrantLock需要手动加锁和解锁,且解锁的操作尽量要放在finally代码块中,保证线程正确释放锁。ReentrantLock操作较为复杂,但是因为可以手动控制加锁和解锁过程,在复杂的并发场景中能派上用场。

  2. ReentrantLock和synchronized都是可重入的。

    • synchronized因为可重入,因此可以放在被递归执行的方法上,且不用担心线程最后能否正确释放锁;

    • 而ReentrantLock在重入时要确保重复获取锁的次数必须和重复释放锁的次数一样,否则可能导致其他线程无法获得该锁。

  3. ReentrantLock可以实现公平锁

    • 公平锁是指当锁可用时,在锁上等待时间最长的线程将获得锁的使用权。而非公平锁则随机分配这种使用权。

    • 和synchronized一样,默认的ReentrantLock实现是非公平锁,因为相比公平锁,非公平锁性能更好。当然公平锁能防止饥饿,某些情况下也很有用。

    • 在创建ReentrantLock的时候通过传进参数true创建公平锁,如果传入的是false或没传参数则创建的是非公平锁

      ReentrantLock lock = new ReentrantLock(true);
  4. ReentrantLock可响应中断

    • 当使用synchronized实现锁时,阻塞在锁上的线程除非获得锁否则将一直等待下去,也就是说这种无限等待获取锁的行为无法被中断

    • 而ReentrantLock提供了一个可以响应中断的获取锁的方法lockInterruptibly()。该方法可以用来解决死锁问题

  5. 获取锁时限时等待

    ReentrantLock还提供了获取锁限时等待的方法tryLock(),可以选择传入时间参数,表示等待指定的时间,无参则表示立即返回锁申请的结果:true表示获取锁成功,false表示获取锁失败。可以使用该方法配合失败重试机制来更好的解决死锁问题。

ReentrantLock实现同步

package ReentrantLockTest;
​
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
​
//ReentrantLock实现同步
public class ReenTrantTest1 {
    public static void main(String[] args) {
        Service service = new Service();
​
        MyThread t1 = new MyThread(service);
        MyThread t2 = new MyThread(service);
        MyThread t3 = new MyThread(service);
        MyThread t4 = new MyThread(service);
        MyThread t5 = new MyThread(service);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }
​
}
class Service {
    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();//释放锁
    }
}
class MyThread extends Thread{
    private Service service;
    public MyThread(Service service){
        this.service=service;
    }
​
    @Override
    public void run() {
        service.testMethod();
    }
}
/*
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-3 1
ThreadName=Thread-3 2
ThreadName=Thread-3 3
ThreadName=Thread-3 4
ThreadName=Thread-3 5
ThreadName=Thread-4 1
ThreadName=Thread-4 2
ThreadName=Thread-4 3
ThreadName=Thread-4 4
ThreadName=Thread-4 5
 */

  

ReentrantLock结合Condition的await()、signal()实现有选择的wait()/notify()功能

package ReentrantLockTest;
​
import java.util.concurrent.locks.*;
​
//ReentrantLock结合Condition的await()、signal()实现有选择的wait()/notify()功能
public class ReentrantLock_Condition {
    public static void main(String[] args) {
        Service1 service1 = new Service1();
        AThread t1 = new AThread(service1);
        BThread t2 = new BThread(service1);
        t1.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
    }
}
class Service1{
    private Lock lcok=new ReentrantLock();
    private Condition condition=lcok.newCondition();
    public void await(){
        try {
            lcok.lock();
            System.out.println("await时间为:"+System.currentTimeMillis());
            condition.await();
            System.out.println("...await之后的语句会在signal执行之后继续执行");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lcok.unlock();
        }
    }
    public void signal(){
        try {
            lcok.lock();
            System.out.println("signal的时间为:"+System.currentTimeMillis());
            condition.signal();
        } finally {
            lcok.unlock();
        }
    }
}
class AThread extends Thread{
    private Service1 service1;
    public AThread(Service1 service1){
        this.service1=service1;
    }
​
    @Override
    public void run() {
        service1.await();
    }
}
class BThread extends Thread{
    private Service1 service1;
    public BThread(Service1 service1){
        this.service1=service1;
    }
​
    @Override
    public void run() {
        service1.signal();
    }
}

  

Unsafe

执行await()方法实现线程的暂停运行的原理是:并发包源代码内部执行了 Unsafe 类的public native void park(boolean isAbsoult, long time);

public native void park(boolean isAbsoult, long time);

http://cnblogs.com/throwable/p/9139947.html

http://blog.csdn.net/sinat_27593959/article/details/103637818

可以通过反射的方式来创建一个实例来:

Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);

通过这个Unsafe实例,可以进行内存管理、线程挂起和恢复、多线程同步、内存屏障等

使用多个Condition可以实现堆指定线程的唤醒

package ReentrantLockTest;
​
import java.util.concurrent.locks.*;
​
//ReentrantLock结合Condition的await()、signal()实现有选择的wait()/notify()功能
public class ReentrantLock_Condition {
    public static void main(String[] args) {
        Service1 service1 = new Service1();
        AThread t1 = new AThread(service1);
        BThread t2 = new BThread(service1);
        t1.start();
        t2.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        service1.signalA();
    }
}
class Service1{
    private Lock lcok=new ReentrantLock();
    private Condition conditionA=lcok.newCondition();
    private Condition conditionB=lcok.newCondition();
    public void awaitA(){
        try {
            lcok.lock();
            System.out.println(Thread.currentThread().getName()+"await时间为:"+System.currentTimeMillis());
            conditionA.await();
            System.out.println(Thread.currentThread().getName()+"...await之后的语句会在signal执行之后继续执行");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lcok.unlock();
        }
    }
    public void awaitB(){
        try {
            lcok.lock();
            System.out.println(Thread.currentThread().getName()+"await时间为:"+System.currentTimeMillis());
            conditionB.await();
            System.out.println(Thread.currentThread().getName()+"...await之后的语句会在signal执行之后继续执行");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lcok.unlock();
        }
    }
    public void signalA(){
        try {
            lcok.lock();
            System.out.println("signal的时间为:"+System.currentTimeMillis());
            conditionA.signalAll();
        } finally {
            lcok.unlock();
        }
    }
    public void signalB(){
        try {
            lcok.lock();
            System.out.println("signal的时间为:"+System.currentTimeMillis());
            conditionB.signalAll();
        } finally {
            lcok.unlock();
        }
    }
}
class AThread extends Thread{
    private Service1 service1;
    public AThread(Service1 service1){
        this.service1=service1;
    }
​
    @Override
    public void run() {
        service1.awaitA();
    }
}
class BThread extends Thread{
    private Service1 service1;
    public BThread(Service1 service1){
        this.service1=service1;
    }
​
    @Override
    public void run() {
        service1.awaitB();
    }
}
/*
Thread-0await时间为:1609579565800
Thread-1await时间为:1609579565801
signal的时间为:1609579566297
Thread-0...await之后的语句会在signal执行之后继续执行//只唤醒了A线程
 */

  

实现生产者/消费者多对多交替输出

 

可能会出现死锁

package ReentrantLockTest;
​
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
​
//使用ReentrantLock和Condition实现生产者/消费者多对多交替输出
public class AlternateTest {
    public static void main(String[] args) {
        Service2 service2 = new Service2();
        setThread[] setThread = new setThread[10];
        getThread[] getThread = new getThread[10];
        for(int i=0;i<10;i++){
            setThread[i]=new setThread(service2);
            getThread[i]=new getThread(service2);
            setThread[i].start();
            getThread[i].start();
​
        }
​
    }
​
}
class Service2 {
    private Lock 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("生产:★");
            hasValue=true;
            condition.signalAll();
           //condition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void get(){
        try {
            lock.lock();
            if(hasValue==false){
                condition.await();
            }
            System.out.println("消耗:⭐");
            hasValue=false;
            condition.signalAll();//其实也会出现死锁??
            //condition.signal();//出现死锁
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
class getThread extends Thread{
    private Service2 service2;
    public getThread(Service2 service2){
        this.service2=service2;
    }
​
    @Override
    public void run() {
        service2.get();
    }
}
class setThread extends Thread{
    private Service2 service2;
    public setThread(Service2 service2){
        this.service2=service2;
    }
​
    @Override
    public void run() {
        service2.set();
    }
}

 实现线程的交替打印

package Alternate;
​
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
​
//实现线程的交替执行
public class AlternateExe {
    public static void main(String[] args) {
        Service service = new Service();
        for(int i=0;i<5;i++){
            MyThread3 t3 = new MyThread3(service);
            MyThread2 t2 = new MyThread2(service);
            MyThread1 t1 = new MyThread1(service);
            t1.start();
            t2.start();
            t3.start();
​
        }
    }
}
class Service{
   private Lock lcok= new ReentrantLock();
   private Condition condition=lcok.newCondition();
​
  volatile private int nextWhoPrint=1;//volatile可以省略
public void test1(){
       try {
           lcok.lock();
           while(nextWhoPrint!=1)
               condition.await();
           System.out.println("AAA");
           nextWhoPrint=2;
           condition.signalAll();
       } catch (InterruptedException e) {
           e.printStackTrace();
       } finally {
           lcok.unlock();
       }
​
   }
   public void test2(){
       try {
           lcok.lock();
           while(nextWhoPrint!=2)
               condition.await();
           System.out.println("BBB");
           nextWhoPrint=3;
           condition.signalAll();
       } catch (InterruptedException e) {
           e.printStackTrace();
       } finally {
           lcok.unlock();
       }
​
   }
   public void test3(){
       try {
           lcok.lock();
           while(nextWhoPrint!=3)
               condition.await();
           System.out.println("CCC");
           nextWhoPrint=1;
           condition.signalAll();
       } catch (InterruptedException e) {
           e.printStackTrace();
       } finally {
           lcok.unlock();
       }
   }
}
class MyThread1 extends Thread{
    private Service service;
    public MyThread1(Service service){
        this.service=service;
    }
​
    @Override
    public void run() {
        service.test1();
    }
}
class MyThread2 extends Thread{
    private Service service;
    public MyThread2(Service service){
        this.service=service;
    }
​
    @Override
    public void run() {
        service.test2();
    }
}
class MyThread3 extends Thread{
    private Service service;
    public MyThread3(Service service){
        this.service=service;
    }
​
    @Override
    public void run() {
        service.test3();
    }
}
/*
AAA
BBB
CCC
AAA
BBB
CCC
AAA
BBB
CCC
AAA
BBB
CCC
AAA
BBB
CCC
*/

 

原文地址:https://www.cnblogs.com/learnjavajava/p/14520417.html