Java NIO-锁机制Lock

Java NIO提供Lock对象来实现对当前对象加锁。

1,Lock接口方法详解:

  • void lock()

    获取锁。如果锁不可用,出现线程调度,将会禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态。

  • void lockInterruptibly() throws InterruptedException;

    如果当前线程未被中断则获取锁。如果锁可用则获取锁,并立即返回。如果锁不可用出现线程调度会禁用当前线程,除非发生以下情况,否则该线程会一直休眠:-1,当前线程获取锁。-2,其他线程终端当前线程,并且该线程支持对锁获取的中断。

  • boolean tryLock()

    仅在调用时锁为空闲状态才获取该锁。如果锁可用则立即获取锁,返回true。如果锁不可用,则此方法返回false。

  • void unlock()

    释放锁。在获取锁操作后,需要进行释放锁。

2,Lock与synchronized

Lock比synchronized更加的灵活,且具有以下优势:

  •     允许以一种更加灵活的方式构造synchronized块。使用synchronized,必须以结构化的方式释放锁。Lock接口允许更加灵活的实现临界区。

  • Lock实现更多额外的功能,比如tryLock

  • Lock支持读写分离。

3,多线程模拟打印队列。

   
   
   
   
  1. package chp1.atomic.print;
  2. import java.util.concurrent.locks.Lock;
  3. import java.util.concurrent.locks.ReentrantLock;
  4. /**
  5. * 打印队列
  6. *
  7. * @author jinglongjun
  8. *
  9. */
  10. public class PrintQueue {
  11. private final Lock queueLock = new ReentrantLock();
  12. /**
  13. * 模拟打印任务
  14. *
  15. * @param document
  16. */
  17. public void printJob(Object document) {
  18. try {
  19. // 获取锁
  20. queueLock.lock();
  21. Long duration = (long) (Math.random() * 10000);
  22. System.out.println(Thread.currentThread().getName()
  23. + ":PrintQueue: Printing a Job during " + (duration / 1000)
  24. + " seconds");
  25. Thread.sleep(duration);
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. } finally {
  29. // 释放锁
  30. queueLock.unlock();
  31. }
  32. }
  33. }

   
   
   
   
  1. package chp1.atomic.print;
  2. public class Job implements Runnable {
  3. private PrintQueue printQueue;
  4. public Job(PrintQueue printQueue) {
  5. this.printQueue = printQueue;
  6. }
  7. @Override
  8. public void run() {
  9. System.out.printf("%s: Going to print a document\n", Thread
  10. .currentThread().getName());
  11. printQueue.printJob(new Object());
  12. System.out.printf("%s: The document has been printed\n", Thread
  13. .currentThread().getName());
  14. }
  15. }

   
   
   
   
  1. package chp1.atomic.print;
  2. public class Main {
  3. public static void main(String[] args) {
  4. PrintQueue printQueue = new PrintQueue();
  5. Thread thread[] = new Thread[10];
  6. for (int i = 0; i < 10; i++) {
  7. thread[i] = new Thread(new Job(printQueue), "Thread " + i);
  8. }
  9. for (int i = 0; i < 10; i++) {
  10. thread[i].start();
  11. }
  12. }
  13. }

4,死锁

通过Lock获取对象的时候,应该特别注意死锁问题,A线程锁定x,B线程锁定y,而当B线程试图锁定x,A视图锁定y的时候即会发生死锁。曾经在面试的时候被要求写一个死锁程序。

   
   
   
   
  1. package chp1.atomic.DeadLock;
  2. public class DeadLock {
  3. public static void main(String[] args) {
  4. final Object x = new Object();
  5. final Object y = new Object();
  6. Thread t1 = new Thread(new Runnable() {
  7. @Override
  8. public void run() {
  9. synchronized (x) {
  10. System.out.println(" t1 synchronized x");
  11. try {
  12. Thread.sleep(1000);
  13. } catch (InterruptedException e) {
  14. e.printStackTrace();
  15. }
  16. synchronized (y) {
  17. System.out.println("t1 synchronized y ");
  18. }
  19. }
  20. }
  21. });
  22. Thread t2 = new Thread(new Runnable() {
  23. @Override
  24. public void run() {
  25. synchronized (y) {
  26. System.out.println(" t2 synchronized y");
  27. try {
  28. Thread.sleep(1000);
  29. } catch (InterruptedException e) {
  30. e.printStackTrace();
  31. }
  32. synchronized (x) {
  33. System.out.println("t2 synchronized x ");
  34. }
  35. }
  36. }
  37. });
  38. t1.start();
  39. t2.start();
  40. }
  41. }

运行时输出以下语句然后一直等待:

   
   
   
   
  1. t1 synchronized x
  2. t2 synchronized y

通过jstack命令可以查看是否存在死锁。

   
   
   
   
  1. jstack -l 33674

    
    
    
    
  1. 2016-04-04 21:35:39
  2. Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.79-b02 mixed mode):
  3. "Attach Listener" daemon prio=5 tid=0x0000000128162000 nid=0x2365f waiting on condition [0x0000000000000000]
  4.   java.lang.Thread.State: RUNNABLE
  5.   Locked ownable synchronizers:
  6. - None
  7. "Process monitor" daemon prio=5 tid=0x0000000102137000 nid=0x1a843 in Object.wait() [0x000070000426b000]
  8.   java.lang.Thread.State: WAITING (on object monitor)
  9. at java.lang.Object.wait(Native Method)
  10. - waiting on <0x00000007f5997a38> (a java.lang.UNIXProcess)
  11. at java.lang.Object.wait(Object.java:503)
  12. at java.lang.UNIXProcess.waitFor(UNIXProcess.java:261)
  13. - locked <0x00000007f5997a38> (a java.lang.UNIXProcess)
  14. at org.eclipse.debug.core.model.RuntimeProcess$ProcessMonitorThread.run(RuntimeProcess.java:426)
  15.   Locked ownable synchronizers:
  16. - None

参考:

http://ifeve.com/basic-thread-synchronization-5/

http://www.blogjava.net/xylz/archive/2010/07/05/325274.html

http://ifeve.com/basic-thread-synchronization-8/

你可能感兴趣的:(java,nio,Lock,死锁,死锁实例)