Java并发编程问题:锁竞争和死锁实例

原创 小咪咪 2024-11-28 01:12 75阅读 0赞

锁竞争和死锁是Java并发编程中常见的两个问题。下面我将分别给出实例解释。

  1. 锁竞争(Race Condition):
    这种情况通常发生在多个线程同时访问共享资源,而这些资源的访问又涉及到锁操作时,可能出现的错误结果。
    例如:

    1. class Counter {
    2. private int count = 0;
    3. public synchronized void increment() {
    4. count++;
    5. notifyAll(); // 唤醒所有等待的线程
    6. }
    7. public synchronized int getCount() {
    8. return count;
    9. }
    10. }
    11. public class Main {
    12. public static void main(String[] args) {
    13. Counter counter = new Counter();
    14. Thread thread1 = new Thread(() -> {
    15. for (int i = 0; i < 5; i++) {
    16. counter.increment(); // 假设这里的操作是正确的
    17. try { // 为了模拟可能的等待情况
    18. wait(100); // 模拟线程在资源竞争中等待的情况
    19. } catch (InterruptedException e) {
    20. e.printStackTrace();
    21. }
    22. }
    23. }));
    24. Thread thread2 = new Thread(() -> {
    25. for (int i = 0; i < 5; i++) {
    26. counter.increment(); // 这里操作错误,可能导致count不增加
    27. try { // 同样模拟等待情况
    28. wait(100); // 线程在资源竞争中等待
    29. } catch (InterruptedException e) {
    30. e.printStackTrace();
    31. }
    32. }
    33. }));
    34. thread1.start(); // 启动线程1,先进行资源访问操作
    35. thread2.start(); // 同时启动线程2,错误操作可能在后启动的线程中发生
    36. 这个例子展示了锁竞争可能导致的结果不一致。为了避免死锁,开发者通常需要遵循适当的并发控制策略。
  2. 死锁(Deadlock):
    死锁是两个或更多的线程在执行过程中,因争夺资源而造成的一种相互等待的现象,且在这种现象中没有任何线程能够推进其执行。

    例如:

    1. class Bank {
    2. private Map<String, Account> accounts = new HashMap<>();
    3. public synchronized void openAccount(String owner) {
    4. Account account = new Account(owner);
    5. if (accounts.containsKey(owner)) { // 冲突,存在多个账户归属同一个拥有者
    6. throw new IllegalArgumentException("Account for " + owner + " already exists.");
    7. } else {
    8. accounts.put(owner, account);
    9. }
    10. }
    11. public synchronized Account getAccount(String owner) {
    12. return accounts.get(owner);
    13. }
    14. }
    15. class Account {
    16. private String owner;
    17. public Account(String owner) {
    18. this.owner = owner;
    19. }
    20. public String getOwner() {
    21. return owner;
    22. }
    23. }
    24. public class Main {
    25. public static void main(String[] args) {
    26. Bank bank = new Bank();
    27. Thread thread1 = new Thread(() -> {
    28. bank.openAccount("User1"); // 创建账户
    29. try { // 模拟线程等待资源
    30. wait(500); // 线程在等待银行账户创建完成时发生等待
    31. } catch (InterruptedException e) {
    32. e.printStackTrace();
    33. }
    34. }));
    35. Thread thread2 = new Thread(() -> {
    36. bank.openAccount("User2"); // 冲突,试图创建已经被其他线程占用的账户
    37. try { // 与线程1类似,模拟线程等待资源冲突发生
    38. wait(500); // 线程在等待银行账户创建完成时发生等待
    39. } catch (InterruptedException e) {
    40. e.printStackTrace();
    41. }
    42. }));
    43. thread1.start(); // 启动创建第一个用户账户的线程
    44. thread2.start(); // 同时启动尝试创建第二个用户账户,但已由线程1占用的线程
    45. 这个例子展示了死锁可能的情况。两个线程同时对银行资源进行访问,当一个线程在获取资源后等待另一个线程释放资源时,如果这时又有线程试图获取已被其他线程占用的资源,就会导致所有线程都无法推进执行,从而形成死锁。
文章版权声明:注明蒲公英云原创文章,转载或复制请以超链接形式并注明出处。

发表评论

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

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

相关阅读