Java中的并发编程:锁竞争、死锁等问题实例

原创 小鱼儿 2024-10-13 11:06 126阅读 0赞

在Java中,并发编程涉及多个方面,包括锁竞争、死锁等。以下是一些实例:

  1. 锁竞争:
    a. 代码示例:

    1. ```java
    2. // 假设我们有两个共享资源对象resourceA和resourceB
    3. class Resource {
    4. private Object obj;
    5. private Lock lock;
    6. // 构造器,初始化锁
    7. Resource(Object obj, Lock lock) {
    8. this.obj = obj;
    9. this.lock = lock;
    10. }
    11. }
    12. // 同步访问资源
    13. void accessResource(Resource resourceA, Resource resourceB) {
    14. resourceA.lock.lock();
    15. try {
    16. // 共享资源操作
    17. System.out.println("Accessing resource A");
    18. resourceB.lock.lock();
    19. try {
    20. // 再次共享资源操作
    21. System.out.println("Accessing resource B");
    22. } finally {
    23. // 释放锁
    24. resourceB.lock.unlock();
    25. resourceA.lock.unlock();
    26. }
    27. } catch (Exception e) {
    28. // 锁竞争异常处理
    29. e.printStackTrace();
    30. }
    31. }
    32. ```

    b. 现象:如果两个线程同时访问资源A和资源B,可能会因为锁的争抢而导致执行顺序混乱。

  2. 死锁:
    a. 产生条件:

    • 循环等待:一个线程等待另一个线程释放已获得的锁。
    • 不可进入状态:线程因等待资源而进入的一种阻塞状态,此时线程无法进行任何操作。

    b. 示例:

    1. ```java
    2. // 假设我们有四个共享资源对象
    3. class Resource {
    4. private Object obj;
    5. private Lock lock;
    6. // 构造器,初始化锁
    7. Resource(Object obj, Lock lock) {
    8. this.obj = obj;
    9. this.lock = lock;
    10. }
    11. }
    12. // 线程1 - 需要resourceA和resourceB
    13. class Thread1 extends Thread {
    14. private Resource resourceA, resourceB;
    15. public Thread1(Resource resourceA, Resource resourceB) {
    16. this.resourceA = resourceA;
    17. this.resourceB = resourceB;
    18. }
    19. @Override
    20. public void run() {
    21. try {
    22. // 获取资源锁
    23. resourceA.lock.lock();
    24. resourceB.lock.lock();
    25. System.out.println("Thread1 started");
    26. // 线程操作,这里假设是执行一些耗时的操作
    27. Thread.sleep(2000); // 模拟耗时操作
    28. // 共享资源释放
    29. resourceB.unlock();
    30. resourceA.unlock();
    31. System.out.println("Thread1 finished");
    32. } catch (InterruptedException | Exception e) {
    33. e.printStackTrace();
    34. } finally {
    35. // 释放所有锁
    36. resourceB.lock.unlock();
    37. resourceA.lock.unlock();
    38. }
    39. }
    40. }
    41. // 线程2 - 需要resourceB和resourceC
    42. class Thread2 extends Thread {
    43. private Resource resourceB, resourceC;
    44. public Thread2(Resource resourceB, Resource resourceC) {
    45. this.resourceB = resourceB;
    46. this.resourceC = resourceC;
    47. }
    48. @Override
    49. public void run() {
    50. try {
    51. // 获取资源锁
    52. resourceB.lock.lock();
    53. resourceC.lock.lock();
    54. System.out.println("Thread2 started");
    55. // 线程操作,这里假设是执行一些耗时的操作
    56. Thread.sleep(1500); // 模拟耗时操作
    57. // 共享资源释放
    58. resourceC.unlock();
    59. resourceB.unlock();
    60. System.out.println("Thread2 finished");
    61. } catch (InterruptedException | Exception e) {
    62. e.printStackTrace();
    63. } finally {
    64. // 释放所有锁
    65. resourceC.lock.unlock();
    66. resourceB.lock.unlock();
    67. }
    68. }
    69. }
    70. // 启动线程
    71. Thread1 thread1 = new Thread1(resourceA, resourceB));
    72. thread1.start();
    73. Thread2 thread2 = new Thread2(resourceB, resourceC));
    74. thread2.start();
    75. // 程序结束,等待所有线程完成
    76. while (thread1.isAlive() || thread2.isAlive()) {
    77. try {
    78. // 线程等待
    79. Thread.sleep(100); // 模拟等待时间
    80. } catch (InterruptedException e) {
    81. e.printStackTrace();
    82. }
    83. }
    84. System.out.println("All threads finished.");

    }
    }
    ```

在这个例子中,线程1和线程2需要共享资源A、B和C。如果两个线程同时访问这些资源,可能会导致死锁。注意这个例子是模拟的,实际编程时需要考虑线程安全和异常处理等问题。

文章版权声明:注明蒲公英云原创文章,转载或复制请以超链接形式并注明出处。

发表评论

表情:
评论列表 (有 0 条评论,126人围观)

还没有评论,来说两句吧...

相关阅读