Reentrantlock
JDK1.5新增的ReentrantLock类,重入锁。
ReentrantLock是独占锁且可重入的
相同点:
ReentrantLock和synchronized都是独占锁,只允许线程互斥的访问临界区
ReentrantLock和synchronized都是可重入的
不同点:
synchronized加锁解锁的过程是隐式的,用户不用手动操作,优点是操作简单,但显得不够灵活;ReentrantLock需要手动加锁和解锁,且解锁的操作尽量要放在finally代码块中,保证线程正确释放锁。ReentrantLock操作较为复杂,但是因为可以手动控制加锁和解锁过程,在复杂的并发场景中能派上用场。
ReentrantLock和synchronized都是可重入的。
synchronized因为可重入,因此可以放在被递归执行的方法上,且不用担心线程最后能否正确释放锁;
而ReentrantLock在重入时要确保重复获取锁的次数必须和重复释放锁的次数一样,否则可能导致其他线程无法获得该锁。
ReentrantLock可以实现公平锁
公平锁是指当锁可用时,在锁上等待时间最长的线程将获得锁的使用权。而非公平锁则随机分配这种使用权。
和synchronized一样,默认的ReentrantLock实现是非公平锁,因为相比公平锁,非公平锁性能更好。当然公平锁能防止饥饿,某些情况下也很有用。
在创建ReentrantLock的时候通过传进参数true
创建公平锁,如果传入的是false
或没传参数则创建的是非公平锁
ReentrantLock lock = new ReentrantLock(true);
ReentrantLock可响应中断
当使用synchronized实现锁时,阻塞在锁上的线程除非获得锁否则将一直等待下去,也就是说这种无限等待获取锁的行为无法被中断
而ReentrantLock提供了一个可以响应中断的获取锁的方法lockInterruptibly()
。该方法可以用来解决死锁问题。
获取锁时限时等待
ReentrantLock还提供了获取锁限时等待的方法tryLock()
,可以选择传入时间参数,表示等待指定的时间,无参则表示立即返回锁申请的结果:true表示获取锁成功,false表示获取锁失败。可以使用该方法配合失败重试机制来更好的解决死锁问题。
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 */
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(); } }
执行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实例,可以进行内存管理、线程挂起和恢复、多线程同步、内存屏障等
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