各种同步工具使用
1. 如何使用 ReentrantLock 中的 可中断锁防止死锁?
答: 在 执行语句前 加 可中断锁,此时,当被打断时,会抛出 被中断异常,这样就可以解锁。
注意:要外部中断,死锁中的线程不会自己中断
public class ReentrantLockTest { static Lock lock1 = new ReentrantLock(); static Lock lock2 = new ReentrantLock(); public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new ThreadDemo(lock1, lock2));//该线程先获取锁1,再获取锁2 Thread thread1 = new Thread(new ThreadDemo(lock2, lock1));//该线程先获取锁2,再获取锁1 thread.start(); thread1.start(); thread.interrupt();//是第一个线程中断,这个地方也可以弄一个线程 专门检查死锁,然后中断其中一个线程 } static class ThreadDemo implements Runnable { Lock firstLock; Lock secondLock; public ThreadDemo(Lock firstLock, Lock secondLock) { this.firstLock = firstLock; this.secondLock = secondLock; } @Override public void run() { try { firstLock.lockInterruptibly(); TimeUnit.MILLISECONDS.sleep(10);//更好的触发死锁 secondLock.lockInterruptibly(); } catch (InterruptedException e) { e.printStackTrace(); } finally { firstLock.unlock(); secondLock.unlock(); System.out.println(Thread.currentThread().getName()+"正常结束!"); } } } }
2. ReentrantLock还给我们提供了获取锁限时等待的方法tryLock(),可以选择传入时间参数,表示等待指定的时间,无参则表示立即返回锁申请的结果:true表示获取锁成功,false表示获取锁失败。我们可以使用该方法配合失败重试机制来更好的解决死锁问题。
例子:
package com.xuecheng.manage_cms; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; /** * 同步控制工具 ReentrantLock */ public class ReentrantLockTest implements Runnable{ private ReentrantLock lock = new ReentrantLock(); @Override public void run() { try { if(lock.tryLock(5, TimeUnit.SECONDS)){ Thread.sleep(6000); }else{ System.out.println("get lock fail"); } } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); System.out.println("lock unlocked"); } } public static void main(String[] args) { ReentrantLockTest task = new ReentrantLockTest(); Thread thread1 = new Thread(task); Thread thread2 = new Thread(task); thread1.start(); thread2.start(); } }
执行结果为:
get lock fail Exception in thread "Thread-1" java.lang.IllegalMonitorStateException at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151) at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261) at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457) at com.xuecheng.manage_cms.ReentrantLockTest.run(ReentrantLockTest.java:24) at java.lang.Thread.run(Thread.java:745) lock unlocked
抛出异常原因为: 获取锁失败的线程 并没有持有监视器的锁,却释放了监视器的锁
3. 读写锁
public class ReadAndWriteLockTest { public static ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); public static void main(String[] args) { //同时写 ExecutorService service = Executors.newCachedThreadPool(); service.execute(new Runnable() { @Override public void run() { writeFile(Thread.currentThread()); } }); service.execute(new Runnable() { @Override public void run() { writeFile(Thread.currentThread()); } }); } // 读操作 public static void readFile(Thread thread) { lock.readLock().lock(); boolean readLock = lock.isWriteLocked(); if (!readLock) { System.out.println("当前为读锁!"); } try { for (int i = 0; i < 5; i++) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(thread.getName() + ":正在进行读操作……"); } System.out.println(thread.getName() + ":读操作完毕!"); } finally { System.out.println("释放读锁!"); lock.readLock().unlock(); } } // 写操作 public static void writeFile(Thread thread) { lock.writeLock().lock(); boolean writeLock = lock.isWriteLocked(); if (writeLock) { System.out.println("当前为写锁!"); } try { for (int i = 0; i < 5; i++) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(thread.getName() + ":正在进行写操作……"); } System.out.println(thread.getName() + ":写操作完毕!"); } finally { System.out.println("释放写锁!"); lock.writeLock().unlock(); } } }
4. 阻塞队列BlockingQuene 的使用
问题: 阻塞队列中 存和取方法是互斥的吗?
public class BlockingQueueExample { public static void main(String[] args) throws Exception { BlockingQueue queue = new ArrayBlockingQueue(1024); Producer producer = new Producer(queue); Consumer consumer = new Consumer(queue); new Thread(producer).start(); new Thread(consumer).start(); Thread.sleep(4000); } }
4.1 生产者
public class Producer implements Runnable{ protected BlockingQueue queue = null; public Producer(BlockingQueue queue) { this.queue = queue; } public void run() { try { queue.put("1"); Thread.sleep(1000); queue.put("2"); Thread.sleep(1000); queue.put("3"); } catch (InterruptedException e) { e.printStackTrace(); } } }
4.2 消费者
public class Consumer implements Runnable{ protected BlockingQueue queue = null; public Consumer(BlockingQueue queue) { this.queue = queue; } public void run() { try { System.out.println(queue.take()); System.out.println(queue.take()); System.out.println(queue.take()); } catch (InterruptedException e) { e.printStackTrace(); }
}
}

浙公网安备 33010602011771号