如何做到当某线程拿不到锁时不继续等待立刻退出?

一、代码

1、Worker类

package com.leslie.test;

import java.util.concurrent.locks.ReentrantLock;

public class Worker {
    private Object o = new Object();
    private ReentrantLock lock = new ReentrantLock();

    public void work1(String action) {
        System.out.println(action + " start");
        synchronized (o) {
            System.out.println(action + " work");
        }
        System.out.println(action + " over");
    }

    public void work2(String action) {
        System.out.println(action + " start");
        if (lock.tryLock()) {
            System.out.println(action + " work");
        }
        System.out.println(action + " over");
    }

    public void work3(String action) {
        System.out.println(action + " start");
        try {
            lock.lockInterruptibly();
            lock.lock();
            System.out.println(action + " work");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        System.out.println(action + " over");
    }
}

2、测试启动类

package com.leslie.test;

public class Tester {
    private static final Worker worker = new Worker();
    
    public static void testSynchronized(){
        Thread t1 = new Thread(){
            public void run() {worker.work1("A");}
        };
        Thread t2 = new Thread(){
            public void run() {worker.work1("B");}
        };
        Thread t3 = new Thread(){
            public void run() {worker.work1("C");}
        };
        Thread t4 = new Thread(){
            public void run() {worker.work1("D");}
        };
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
    public static void testTryLock(){
        Thread t1 = new Thread(){
            public void run() {worker.work2("A");}
        };
        Thread t2 = new Thread(){
            public void run() {worker.work2("B");}
        };
        Thread t3 = new Thread(){
            public void run() {worker.work2("C");}
        };
        Thread t4 = new Thread(){
            public void run() {worker.work2("D");}
        };
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
    public static void testLockInterruptibly(){
        Thread t1 = new Thread(){
            public void run() {worker.work3("A");}
        };
        Thread t2 = new Thread(){
            public void run() {worker.work3("B");}
        };
        Thread t3 = new Thread(){
            public void run() {worker.work3("C");}
        };
        Thread t4 = new Thread(){
            public void run() {worker.work3("D");}
        };
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
    public static void main(String[] args) {
        testSynchronized();
    }
}

3、测试结果

testSynchronized()执行结果:

A start
A work
A over
C start
C work
B start
B work
B over
C over
D start
D work
D over

testTryLock()执行结果:

B start
B work
B over
D start
D over
A start
A over
C start
C over

testLockInterruptibly()执行结果:

A start
D start
B start
C start
A work
A over

二、说明

1、使用synchronized加锁时,拿不到锁的线程会一直等待直到得到锁才继续执行,并不会退出。

2、使用lock.tryLock()的方式只能保证拿不到锁的线程不会执行tryLock(){}包括起来的代码,不在这个范围内的后续代码当拿到锁以后还会执行。

3、使用lock.lockInterruptibly()时,拿不到锁的线程执行到这一句就会判断当前线程是否拥有lock,一旦发现lock已经锁住就结束线程,不会执行后续代码。

补充:上面第3点不可取,虽然拿不到锁的线程不会继续执行下去,但这些线程会保持休眠状态(参考http://hi.baidu.com/gefforey520/item/202295fcf256e35fc8f3370a):

Acquires the lock if it is not held by another thread and returns immediately, setting the lock hold count to one.

If the current thread already holds this lock then the hold count is incremented by one and the method returns immediately.

If the lock is held by another thread then the current thread becomes disabled for thread scheduling purposes and lies dormant until one of two things happens:

  • The lock is acquired by the current thread; or
  • Some other thread the current thread.

原文地址:https://www.cnblogs.com/mabaishui/p/2956993.html