并发编程陷阱:Java多线程并发错误示例

原创 今天药忘吃喽~ 2024-11-23 02:00 34阅读 0赞

在编写和执行Java多线程程序时,可能会遇到一些并发错误。以下是一些典型的错误示例:

  1. 死锁
    此现象发生在两个或多个线程互相等待对方释放资源的情况。
    示例代码(避免死锁的一种方式是使用超时或者条件变量):

    1. // 线程A和B,共享资源r1和r2
    2. class ThreadA extends Thread {
    3. private Object r1;
    4. public ThreadA(Object r1) {
    5. this.r1 = r1;
    6. }
    7. @Override
    8. public void run() {
    9. synchronized (r1) { // 互斥使用r1
    10. r1.notifyAll(); // 唤醒等待r1的线程
    11. }
    12. try {
    13. r1.wait(); // 等待被通知的r1
    14. } catch (InterruptedException e) {
    15. e.printStackTrace();
    16. }
    17. }
    18. }
    19. class ThreadB extends Thread {
    20. private Object r2;
    21. public ThreadB(Object r2) {
    22. this.r2 = r2;
    23. }
    24. @Override
    25. public void run() {
    26. synchronized (r2) { // 互斥使用r2
    27. r2.notifyAll(); // 唤醒等待r2的线程
    28. }
    29. try {
    30. r2.wait(); // 等待被通知的r2
    31. } catch (InterruptedException e) {
    32. e.printStackTrace();
    33. }
    34. }
    35. }
    36. ThreadA threadA = new ThreadA(r1);
    37. ThreadB threadB = new ThreadB(r2);
    38. threadA.start(); // 开始线程A
    39. threadB.start(); // 开始线程B
    40. // 等待两个线程都执行完毕
    41. threadA.join();
    42. threadB.join();
  2. 竞态条件(Race Condition)
    当多个线程同时访问和修改共享资源时,可能会导致结果不一致。
    示例代码:

    1. class Counter {
    2. private int count;
    3. public Counter() {
    4. count = 0;
    5. }
    6. public synchronized void increment() {
    7. count++;
    8. }
    9. public synchronized int getValue() {
    10. return count;
    11. }
    12. }
    13. // 多个线程共享的资源
    14. Counter counter = new Counter();
    15. ThreadA threadA = new ThreadA(counter);
    16. ThreadB threadB = new ThreadB(counter);
    17. threadA.start(); // 开始线程A
    18. threadB.start(); // 开始线程B
    19. // 等待两个线程都执行完毕
    20. threadA.join();
    21. threadB.join();
    22. System.out.println("Counter Value: " + counter.getValue()); // 输出结果
  3. 无锁编程(Lock-Free Programming)错误
    当多线程需要避免同步锁时,可能会出现数据不一致的情况。
    例如,在一个计数器的更新过程中,如果直接改变共享变量而没有锁定或原子操作,就可能引发竞态条件。

  4. 资源泄漏(Resource Leak)
    如果线程在执行完毕后没有正确释放它所持有的资源,那么这些资源可能会一直被占用。
    例如,使用Thread.currentThread().getName()获取当前线程名,如果在线程结束时忘记关闭这个连接,就会导致资源泄漏。

通过理解和避免以上错误,可以编写更健壮、高效的多线程程序。

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

发表评论

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

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

相关阅读