在jdk1.5后新增的ReentrantLock类同样可达到此效果,且在使用上比synchronized更加灵活
相关API:使用ReentrantLock实现同步
lock:
lock()方法:上锁
unlock()方法:释放锁
在jvm层面上,lock是一个java类,lock可以判断是否获取到锁 ,lock需要手动释放锁。
lock不会一直等待,如果获取不到锁,不用等待就可以结束,lock适合大量同步代码的同步问题。
使用:
private Lock lock=new ReentrantLock();
public static void main(String[] args) {
/**
* lock获取锁 和释放锁 需要自定义
*/
ThreadLockTest threadLockTest = new ThreadLockTest();
threadLockTest.lockThread();
threadLockTest.lockThread2();
}
public void lockThread() {
new Thread(new Runnable() {
@Override
public void run() {
try{
System.out.printf(Thread.currentThread().getName()+"获取到锁1");
//获取锁
lock.lock();
System.out.printf(Thread.currentThread().getName()+"获取到锁2");
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
},"t1").start();
}
public void lockThread2() {
new Thread(new Runnable() {
@Override
public void run() {
try{
System.out.printf(Thread.currentThread().getName()+"获取到锁1");
//获取锁
lock.lock();
System.out.printf(Thread.currentThread().getName()+"获取到锁2");
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
},"t2").start();
}
结果:
t1获取到锁1
t1获取到锁2
t2获取到锁1
t2获取到锁2
synchoronized:
synchoronized是java内置关键字,synchoronized无法判断是否获取到锁的态,synchoronized会自动释放锁(执行完成或者发生异常),synchoronized线程阻塞时会一直等待,synchoronized适合少量代码的同步问题。
Condition方法:
使用Condition 实现等待/通知类似于wait()和notify()及notifyAll() Lock锁底层基于AQS实现,需要自己封装实现自旋锁。
condition.signal();唤醒
condition.await();阻塞
方法使用:
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public static void main(String[] args) {
ThreadLockTest threadLockTest = new ThreadLockTest();
//lock 阻塞
threadLockTest.conditionAwait();
try{
Thread.sleep(3000);
}catch (Exception e){
}
//lock 唤醒
threadLockTest.conditionSignal();
}
public void conditionSignal() {
try {
lock.lock();
//类似于synchronized的notity() 需要在获取到lock锁的前提下使用
System.out.printf(Thread.currentThread().getName() + "唤醒");
condition.signal();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
public void conditionAwait() {
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.printf(Thread.currentThread().getName() + "获取锁开始");
//获取锁
lock.lock();
//主动释放锁,同时线程变为阻塞状态 需要在获取到lock锁的前提下使用
System.out.printf(Thread.currentThread().getName() + "主动释放锁,阻塞");
condition.await();
System.out.printf(Thread.currentThread().getName() + "结束");
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放锁
lock.unlock();
}
}
}, "t1").start();
}
t1获取锁开始
t1主动释放锁,阻塞
main3秒后,唤醒
t1结束