Thread详解14:ReentrantLock的用法(二)

来源:互联网 发布:wto贸易数据库 编辑:程序博客网 时间:2024/05/02 01:05

1 lockInterruptibly()

如果当前线程未被中断,则获取锁;如果已经被中断则抛出异常。

package testReentrantLock;import java.util.concurrent.locks.ReentrantLock;public class TestlockInterruptibly extends Thread {    private ReentrantLock lock;    private String name;    public TestlockInterruptibly(String name, ReentrantLock lock) {        super(name);        this.name = name;        this.lock = lock;    }    @Override    public void run() {        super.run();        try {            if (name.equals("T-lock")) {                lock.lock();            } else {                lock.lockInterruptibly();            }            for (int i = 0; i < 3; i++) {                System.out.println(Thread.currentThread().getName() + " printed " + i);                Thread.sleep(1000);            }        } catch (InterruptedException e) {            e.printStackTrace();            System.out.println("----- catch region -----");        } finally {            System.out.println(Thread.currentThread().getName() + " released the lock!");            lock.unlock();        }    }    public static void main(String[] args) {        ReentrantLock lock = new ReentrantLock();        TestlockInterruptibly t1 = new TestlockInterruptibly("T-interruptibly", lock);        TestlockInterruptibly t2 = new TestlockInterruptibly("T-lock", lock);        t1.start();        t2.start();        // interrupt一定要在start之后,不然没有意义        t1.interrupt();        t1.interrupt();    }}

输出

T-lock printed 0java.lang.InterruptedException    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1219)    at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:340)    at testReentrantLock.TestlockInterruptibly.run(TestlockInterruptibly.java:23)Exception in thread "T-interruptibly" java.lang.IllegalMonitorStateException    at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:155)    at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1260)    at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:460)    at testReentrantLock.TestlockInterruptibly.run(TestlockInterruptibly.java:36)----- catch region -----T-interruptibly released the lock!T-lock printed 1T-lock printed 2T-lock released the lock!

可见,给一个线程打上 interrupt 的标记,对于它用 lock() 获取锁是没有影响的;但是对于一个用 lockInterruptibly() 获取锁的线程是有影响的,它会抛出异常。



2 tryLock()

仅在调用时锁未被另一个线程保持的情况下,才获取该锁。
如果该锁没有被另一个线程保持,并且立即返回 true 值,则将锁的保持计数设置为 1。即使已将此锁设置为使用公平排序策略,但是调用 tryLock() 仍将 立即获取锁(如果有可用的),而不管其他线程当前是否正在等待该锁。在某些情况下,此“闯入”行为可能很有用,即使它会打破公平性也如此。如果希望遵守此锁的公平设置,则使用 tryLock(0, TimeUnit.SECONDS) ,它几乎是等效的(也检测中断)。

如果当前线程已经保持此锁,则将保持计数加 1,该方法将返回 true.如果锁被另一个线程保持,则此方法将立即返回 false 值。

所以,tryLock() 的特性是【闯入】 ,至于它有个boolen返回值但是无所谓,因为ReentrantLock 中有个 isHeldByCurrentThread() 方法也可以判断它是否获得了锁。

package testReentrantLock;import java.util.concurrent.locks.ReentrantLock;public class TestlockInterruptibly extends Thread {    private ReentrantLock lock;    private String name;    public TestlockInterruptibly(String name, ReentrantLock lock) {        super(name);        this.name = name;        this.lock = lock;    }    @Override    public void run() {        super.run();        try {            boolean ret = lock.tryLock();            if (!ret) {                System.out.println(Thread.currentThread().getName() + " failed to get the lock!");            } else {                for (int i = 0; i < 3; i++) {                    System.out.println(Thread.currentThread().getName() + " printed " + i);                    Thread.sleep(1000);                }            }        } catch (InterruptedException e) {            e.printStackTrace();            System.out.println("----- catch region -----");        } finally {            if (lock.isHeldByCurrentThread()) {                System.out.println(Thread.currentThread().getName() + " released the lock!");                lock.unlock();            }        }    }    public static void main(String[] args) {        ReentrantLock lock = new ReentrantLock();        TestlockInterruptibly t1 = new TestlockInterruptibly("T-A", lock);        TestlockInterruptibly t2 = new TestlockInterruptibly("T-B", lock);        t1.start();        t2.start();    }}

输出

T-A printed 0T-B failed to get the lock!T-A printed 1T-A printed 2T-A released the lock!


3 tryLock(long timeout, TimeUnit unit)

如果锁在给定等待时间内没有被另一个线程保持,且当前线程未被 中断,则获取该锁。如果该锁没有被另一个线程保持,并且立即返回 true 值,则将锁的保持计数设置为 1。如果为了使用公平的排序策略,已经设置此锁,并且其他线程都在等待该锁,则不会 获取一个可用的锁。这与 tryLock() 方法相反。如果想使用一个允许闯入公平锁的定时 tryLock,那么可以将定时形式和不定时形式组合在一起:

if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
0 0
原创粉丝点击