继续上一篇文章,synchronized 的功能扩展,重入锁。
- ReenterLock 重入锁
为什么叫重入锁呢?因为锁是可以反复进入的,针对一个线程来说的
与synchronized 比较写一下
第一 ReenterLock 需要手动释放锁,synchronized 不需要
第二 中断响应 对于synchronized 如果一个线程在等待,只有继续执行或等待,但是重入锁可以等待时,进行中断。
reentrantLock.lockInterruptibly();//获得锁,优先中断
第三 限时等待锁
tryLock有二个参数 第一个是等待时长 第二个是单位
例子 tryLock等待5秒 Thread获取锁6秒,所以例子请求锁失败。
mport java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class TryLockTest implements Runnable{
private static ReentrantLock lock=new ReentrantLock();
@Override
public void run() {
try {
if(lock.tryLock(5, TimeUnit.SECONDS)) {
Thread.sleep(6000);
}else {
System.out.println("get lock failed");
}
}catch (Exception e){
e.printStackTrace();
}finally {
if(lock.isHeldByCurrentThread()){
lock.unlock();
}
}
}
public static void main(String args[]){
TryLockTest test=new TryLockTest();
Thread thread1=new Thread(test);
Thread thread2=new Thread(test);
thread1.start();
thread2.start();
}
}
第四 公平锁 例子
import java.util.concurrent.locks.ReentrantLock;
/**o
1. 重入锁 与synchronized
*/
public class RelockTest implements Runnable{
private static ReentrantLock reentrantLock=new ReentrantLock(true);//公平锁
@Override
public void run() {
while (true) {
try {
reentrantLock.lockInterruptibly();//获得锁,优先中断
//reentrantLock.lock();
System.out.println(Thread.currentThread().getId()+"获得锁");
} catch (InterruptedException e) {
} finally {
reentrantLock.unlock();
}
}
}
public static void main(String args[]){
RelockTest relockTest= new RelockTest();
Thread thread1=new Thread(relockTest, "tr1");
Thread thread2=new Thread(relockTest, "tr2");
thread1.start();
thread2.start();
}
}
就是两个线程可以公平的获取线程
2. Condition 条件
signal
void signal()唤醒一个等待线程。
如果所有的线程都在等待此条件,则选择其中的一个唤醒。在从 await 返回之前,该线程必须重新获取锁定。
上个例子:
作为一个示例,假定有一个绑定的缓冲区,它支持 put 和 take 方法。如果试图在空的缓冲区上执行 take 操作,则在某一个项变得可用之前,线程将一直阻塞;如果试图在满的缓冲区上执行 put 操作,则在有空间变得可用之前,线程将一直阻塞。我们喜欢在单独的等待 set 中保存 put 线程和 take 线程,这样就可以在缓冲区中的项或空间变得可用时利用最佳规划,一次只通知一个线程。可以使用两个 Condition 实例来做到这一点。
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
(ArrayBlockingQueue 类提供了这项功能,因此没有理由去实现这个示例类。)
3. 信号量 指定多个线程访问一个资源