Reentrantlock
JDK1.5新增的ReentrantLock类,重入锁。
ReentrantLock是独占锁且可重入的
ReentrantLock和synchronized
相同点:
-
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表示获取锁失败。可以使用该方法配合失败重试机制来更好的解决死锁问题。
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 */