前言:
死锁是多线程编程中常见的问题之一,如果不正确处理,可能会导致程序崩溃或停止响应。为了避免死锁,我们需要了解其根本原因,然后采取相应的措施来解决问题。这包括避免资源分配问题、算法设计问题和代码实现问题等。通过采用上述方法,我们可以有效地减少死锁的风险,并提高多线程应用程序的正确性和可靠性。今天我们就聊聊我们日常写代码时该如何避免死锁的发生。
1、设置超时时间
由于 synchronized不具备尝试锁的能力,可以使用 Lock的tryLock(long timeout, TimeUnit unit) 替代。造成超时的可能性多:发生了死锁、线程陷入死循环、线程执行很慢,无论是哪种情况,只要过了超时时间,就认为失败获取锁失败的时候,要执行一些应对措施:比如打日志、发报警邮件、重启等/** * 堆代码 duidaima.com * 使用Lock中的tryLock()避免死锁 */ publicclass TryLockDeaLock implements Runnable { int flag = 1; static Lock lock1 = new ReentrantLock(); static Lock lock2 = new ReentrantLock(); @Override public void run() { for (int i = 0; i < 100; i++) { if (flag == 1){ try { if (lock1.tryLock(800, TimeUnit.MILLISECONDS)){ System.out.println("线程1,拿到lock1"); Thread.sleep(new Random().nextInt(1000)); if (lock2.tryLock(800,TimeUnit.MILLISECONDS)){ System.out.println("线程1,成功获取到 lock1 & lock2"); //释放 lock2.unlock(); lock1.unlock(); break; }else { System.out.println("线程1,获取lock2,失败,已重试"); lock1.unlock(); Thread.sleep(new Random().nextInt(1000)); } }else { System.out.println("线程1,获取lock1,失败,已重试"); } } catch (InterruptedException e) { e.printStackTrace(); } } if (flag ==0){ try { if (lock2.tryLock(3000, TimeUnit.MILLISECONDS)){ System.out.println("线程2,拿到lock2"); Thread.sleep(new Random().nextInt(1000)); if (lock1.tryLock(3000,TimeUnit.MILLISECONDS)){ System.out.println("线程2,成功获取到 lock1 & lock2"); //释放 lock2.unlock(); lock1.unlock(); break; }else { System.out.println("线程2,获取lock1,失败,已重试"); lock1.unlock(); Thread.sleep(new Random().nextInt(1000)); } }else { System.out.println("线程2,获取lock2,失败,已重试"); } } catch (InterruptedException e) { e.printStackTrace(); } } } } //主函数 public static void main(String[] args) { TryLockDeaLock t1 = new TryLockDeaLock(); TryLockDeaLock t2 = new TryLockDeaLock(); t1.flag = 1; t2.flag = 0; Thread thread1 = new Thread(t1); Thread thread2 = new Thread(t2); thread1.start(); thread2.start(); } }2、多使用并发工具类,而不是自己设计锁
ConcurrentHashMap、ConcurrentLinkedQueue、AtomicBoolean等,实际应用中java.util.concurrent.atomic十分有用,简单方便且效率比使用Lock更高,多用并发集合少用同步集合,并发集合比同步集合的可扩展性更好,并发场景需要用到map,首先想到用ConcurrentHashMap。