Java 锁机制

ReentrantLock

优点
  • 可重入
  • 可中断
  • 可限时
  • 公平锁
一般用法
public class Starter extends Thread {

    public static ReentrantLock lock = new ReentrantLock();
    public static int i = 0;

    public Starter(String name) {
        super.setName(name);
    }

    @Override
    public void run() {
        for (int j = 0; j < 100000; j++) {
            lock.lock();
            try {
                System.out.println(this.getName() + " " + i);
                i++;
            } finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Starter test1 = new Starter("Thread1");
        Starter test2 = new Starter("Thread2");

        test1.start();
        test2.start();
        test1.join();
        test2.join();

        System.out.println(i);
    }

}

// 使用 ReentrantLock,输出结果:
….
Thread2 199959
Thread2 199960
Thread2 199961
199962

// 不使用 ReentrantLock,输出结果:
….
Thread2 199997
Thread2 199998
Thread2 199999
200000

可重入
lock.lock();
lock.lock();
try {
    i++;
}           
finally {
    lock.unlock();
    lock.unlock();
}
可中断
public class Starter extends Thread {

    public static ReentrantLock lock1 = new ReentrantLock();
    public static ReentrantLock lock2 = new ReentrantLock();

    int lock;

    public Starter(int lock, String name) {
        super(name);
        this.lock = lock;
    }

    @Override
    public void run() {
        try {
            if (lock == 1) {
                lock1.lockInterruptibly();
                try {
                    Thread.sleep(500);
                } catch (Exception e) {

                }
                lock2.lockInterruptibly();
            } else {
                lock2.lockInterruptibly();
                try {
                    Thread.sleep(500);
                } catch (Exception e) {

                }
                lock1.lockInterruptibly();
            }
        } catch (Exception e) {

        } finally {
            if (lock1.isHeldByCurrentThread()) {
                lock1.unlock();
            }
            if (lock2.isHeldByCurrentThread()) {
                lock2.unlock();
            }
            System.out.println(Thread.currentThread().getId() + " : 线程退出");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Starter s1 = new Starter(1, "LockInterrupt1");
        Starter s2 = new Starter(2, "LockInterrupt2");
        s1.start();
        s2.start();
        Thread.sleep(1000);

        DeadLockChecker.check();
    }

    static class DeadLockChecker {
        private final static ThreadMXBean mBean = ManagementFactory.getThreadMXBean();

        public static void check() {
            Thread tt = new Thread(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    while (true) {
                        long[] deadLockedThreadIds = mBean.findDeadlockedThreads();
                        if (deadLockedThreadIds != null) {
                            ThreadInfo[] threadInfos = mBean.getThreadInfo(deadLockedThreadIds);
                            for (Thread thread : Thread.getAllStackTraces().keySet()) {
                                for (int i = 0; i < threadInfos.length; i++) {
                                    if (thread.getId() == threadInfos[i].getThreadId()) {
                                        System.out.println(thread.getName());
                                        thread.interrupt();
                                    }
                                }
                            }
                        }
                        try {
                            Thread.sleep(5000);
                        } catch (Exception e) {

                        }
                    }
                }
            });
            tt.setDaemon(true);
            tt.start();
        }
    }

}

输出结果:
LockInterrupt2
LockInterrupt1
11 : 线程退出
10 : 线程退出

可限时
public class Starter extends Thread {

    public static ReentrantLock lock = new ReentrantLock();

    public Starter(String name) {
        super(name);
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            if (lock.tryLock(3, TimeUnit.SECONDS)) {
                Thread.sleep(5000);
            } else {
                System.out.println(this.getName() + " get lock failed");
            }
        } catch (Exception e) {

        } finally {
            if (lock.isHeldByCurrentThread()) {
                System.out.println("lock.isHeldByCurrentThread : " + this.getName());
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        Starter s1 = new Starter("TryLockTest1");
        Starter s2 = new Starter("TryLockTest2");

        s1.start();
        s2.start();
    }

}

输出结果:
TryLockTest1 get lock failed
lock.isHeldByCurrentThread : TryLockTest2

公平锁
public static ReentrantLock fairLock = new ReentrantLock(true);
注意事项

为了保证锁最终被释放,要把互斥区放在 try 里面,释放锁放在 finally 里面。

ReadWriteLock

优点

写线程需要互斥,读线程不需要互斥。

例子
public class Starter {

    private int data;
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    public void set(int data) {
        readWriteLock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " : 准备写入数据");
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.data = data;
            System.out.println(Thread.currentThread().getName() + " : 写入" + this.data);
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }

    public void get() {
        readWriteLock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " : 准备读取数据");
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " : 读取" + this.data);
        } finally {
            readWriteLock.readLock().unlock();
        }
    }

    public static void main(String[] args) {
        final Starter data = new Starter();

        for (int i = 0; i < 3; i++) {
            Thread thread = new Thread(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    for (int j = 0; j < 5; j++) {
                        data.set(new Random().nextInt(30));
                    }
                }
            });
            thread.setName("Thread-w " + i);
            thread.start();
        }

        for (int i = 0; i < 3; i++) {
            Thread thread = new Thread(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    for (int j = 0; j < 5; j++) {
                        data.get();
                    }
                }
            });
            thread.setName("Thread-r " + i);
            thread.start();
        }
    }

}

Condition

例子
public class Starter {
    final Lock lock = new ReentrantLock();
    final Condition notFull = lock.newCondition();
    final Condition notEmpty = lock.newCondition();

    final Object[] items = new Object[100];
    int putPtr;
    int takePtr;
    int 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();
        }
    }
}

参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值