#1 设置超时时间

1 )Lock的tryLock(long timeout, TimeUnit unit)

2 )synchronized不具备 尝试拿取 锁的能力

造成超时的可能性多:死锁、线程执行时间长、线程陷入死循环

获取锁失败:打日志、发报警邮件、重启(大事化小)

代码演示:


import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @description 用trylock避免死锁
 */
public class TryLockDeadLock implements Runnable {
    static Lock lock1 = new ReentrantLock();
    static Lock lock2 = new ReentrantLock();
    private int flag = 1;

    public static void main(String[] args) {
        TryLockDeadLock r1 = new TryLockDeadLock();
        r1.flag = 1;
        TryLockDeadLock r2 = new TryLockDeadLock();
        r2.flag = 0;
        new Thread(r1).start();
        new Thread(r2).start();
    }

    @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获取到了锁1");
                        Thread.sleep(new Random().nextInt(1000));
                        if (lock2.tryLock(800, TimeUnit.MILLISECONDS)) {
                            System.out.println("线程1获取锁1和锁2");

                            lock2.unlock();
                            lock1.unlock();
                            break;
                        } else {
                            System.out.println("线程1获取锁2失败,释放锁1");

                            lock1.unlock();
                            Thread.sleep(new Random().nextInt(1000));
                        }
                    } else {
                        System.out.println("线程1获取锁1失败,已重试");
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            if (flag == 0) {
                try {
                    if (lock2.tryLock(3000, TimeUnit.MILLISECONDS)) {
                        System.out.println("线程2获取到了锁2");
                        Thread.sleep(new Random().nextInt(1000));
                        if (lock1.tryLock(3000, TimeUnit.MILLISECONDS)) {
                            System.out.println("线程2获取锁1和锁2");

                            lock1.unlock();
                            lock2.unlock();
                            break;
                        } else {
                            System.out.println("线程2获取锁1失败,释放锁2");

                            lock2.unlock();
                            Thread.sleep(new Random().nextInt(1000));
                        }
                    } else {
                        System.out.println("线程2获取锁2失败,已重试");
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

2 多使用并发类而不是自己设计锁

1 )ConcurrentHashMap、ConcurrentLinkedQueue、AtomicBoolean

2 )实际应用中java.util.concurrent.atomic使用方便(之前尝试过实现一个使用流的方式

统计读取流写入数据的长度,长度计算使用AtomicLong【因为流可能存在多线程的情

况】),效率比Lock高

代码:

			/**
			*使用流来统计HTTP协议的Content-Length
			*/
			publicclassCounterOutputStreamextendsOutputStream{
			
				/**
				*流的读写是多线程的
				*为了线程安全
				*使用Atomic类
				*/
				private AtomicLong mAtomicLong = new AtomicLong();
				
				/**
				*拿到总长度
				*@return
				*/
				publiclongget(){
					returnmAtomicLong.get();
				}
				
				@Override
				publicvoidwrite(inti)throwsIOException{
					mAtomicLong.addAndGet(1);
				}
				
				publicvoidwrite(longb)throwsIOException{
					mAtomicLong.addAndGet(b);
				}
				
				@Override
				publicvoidwrite(byte[]b)throwsIOException{
					mAtomicLong.addAndGet(b.length);
				}
				
				@Override
				publicvoidwrite(byte[]b,intoff,intlen)throwsIOException{
					mAtomicLong.addAndGet(len);
				}
				
				@Override
				publicvoidflush()throwsIOException{
				
				}
				
				@Override
				publicvoidclose()throwsIOException{
					super.close();
				}
			}

3 )并发集合少用同步集合,并发集合比同步集合的可拓展性好(hashmap

concurrentHashMap)

3 尽量降低锁的使用粒度:用不同的锁而不是只用一种锁(轻量级重量级)

4 能使用 同步代码块(缩小锁的范围) ,就不使用同步方法:自己指定 锁对象

5 给线程起一个有意义的名字(debug和排查事半功倍)

6 避免锁的嵌套:MustDeadLock类

7 分配资源前,看能不能 把资源收回来 :银行家算法

8 不要几个功能用同一把锁(锁对象设置多个), 专锁专用