Java多线程并发问题:锁竞争和死锁示例

原创 怼烎@ 2024-12-11 02:15 87阅读 0赞

在Java多线程编程中,锁竞争(Race Condition)和死锁是常见的并发问题。

  1. 锁竞争示例:
    ```java
    // 创建两个线程A和B
    class MyRunnable implements Runnable {
    private Object lock = new Object();

    // 这个方法将会被线程调用
    @Override
    public void run() {

    1. try {
    2. synchronized (lock) { // 使用同一个锁
    3. System.out.println("Thread " + Thread.currentThread().getName() + " is executing the critical section.");
    4. lock.wait(); // 等待锁释放
    5. }
    6. } catch (InterruptedException e) {
    7. e.printStackTrace();
    8. }

    }
    }

public class Main {
public static void main(String[] args) {
MyRunnable threadA = new MyRunnable();
MyRunnable threadB = new MyRunnable();

  1. // 创建并启动两个线程
  2. Thread threadA1 = new Thread(threadA);
  3. Thread threadB1 = new Thread(threadB);
  4. threadA1.start(); // 启动线程A
  5. threadB1.start(); // 启动线程B
  6. // 此时,锁竞争的问题可能会出现
  7. // 如果两个线程同时执行到synchronized (lock) {代码块}
  8. // 并且都试图获取同一个锁(lock),
  9. // 那么就可能会导致锁竞争问题。
  10. }

}

  1. 2. 死锁示例:
  2. ```java
  3. // 创建两个互斥资源,比如两个房间
  4. class Room {
  5. private Object lock = new Object();
  6. // 获取房间的方法,需要获取锁才能进入
  7. public synchronized void enter() {
  8. System.out.println("Thread " + Thread.currentThread().getName() + " entered the room.");
  9. lock.notify(); // 取消对房间的锁定,让其他线程有机会进入
  10. }
  11. }
  12. public class Main {
  13. public static void main(String[] args) {
  14. Room room1 = new Room();
  15. Room room2 = new Room();
  16. // 创建两个线程A和B,分别尝试获取房间并进入
  17. Thread threadA1 = new Thread(() -> {
  18. System.out.println("Thread " + Thread.currentThread().getName() + " started acquiring room 1.");
  19. try {
  20. room1.enter(); // 尝试获取房间并进入
  21. System.out.println("Room 1 successfully entered by Thread " + Thread.currentThread().getName());
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. }));
  26. Thread threadB1 = new Thread(() -> {
  27. System.out.println("Thread " + Thread.currentThread().getName() + " started acquiring room 2.");
  28. try {
  29. room2.enter(); // 尝试获取房间并进入
  30. System.out.println("Room 2 successfully entered by Thread " + Thread.currentThread().getName());
  31. } catch (InterruptedException e) {
  32. e.printStackTrace();
  33. }
  34. }));
  35. // 启动线程A和B
  36. threadA1.start();
  37. threadB1.start();
  38. try {
  39. // 主线程会等待所有子线程结束后再退出
  40. System.out.println("Main thread is waiting for all subthreads to finish.");
  41. Thread.sleep(5000); // 等待5秒
  42. } catch (InterruptedException e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. }

在上述示例中,两个线程(A和B)分别试图获取两个房间(room1和room2)。由于这两个资源是互斥的,所以每个线程都需要获取并释放锁(lock)才能进入房间。

如果线程A先获得room1的锁,并尝试获取room2的锁。同时,线程B也获得了room2的锁,并尝试获取room1的锁。这样就形成了死锁:两个线程都等待对方释放资源,导致都无法继续执行。

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

发表评论

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

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

相关阅读