并发编程挑战:Java线程同步和死锁问题实例
在Java中,线程同步和死锁是两个主要的并发问题。下面分别给出这两个问题的例子:
- 线程同步问题(使用synchronized关键字)
// 假设我们有一个银行账户类
public class BankAccount {
private int balance;
// 同步方法,确保在同一时刻只有一个线程执行这个方法
public synchronized void deposit(int amount) {
balance += amount;
System.out.println("Deposit: Amount=" + amount + ", Balance=" + balance);
}
// 同步方法,确保在同一时刻只有一个线程执行这个方法
public synchronized void withdraw(int amount) {
if (amount > balance) {
System.out.println("Withdrawal: Amount=" + amount + ", Insufficient balance");
return;
}
balance -= amount;
System.out.println("Withdrawal: Amount=" + amount + ", Balance=" + balance);
}
}
// 示例:两个线程同时存款和取款
public class ThreadExample {
public static void main(String[] args) {
BankAccount account = new BankAccount();
// 创建两个线程,一个存钱,一个取钱
Thread depositThread = new Thread(() -> {
for (int i = 1; i <= 500; i++) {
account.deposit(i);
try {
Thread.sleep(200); // 模拟操作时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}));
Thread withdrawThread = new Thread(() -> {
for (int i = 1; i <= 500; i++) {
account.withdraw(i);
try {
Thread.sleep(200); // 模拟操作时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}));
depositThread.start(); // 开始存款线程
withdrawThread.start(); // 开始取款线程
System.out.println("Program execution complete.");
}
}
这段代码会创建两个线程,一个存款(depositThread),另一个取款(withdrawThread)。由于存款和取款方法都是同步的,因此在运行过程中不会出现同时进行存款和取款的情况,也就避免了死锁问题。
- 死锁问题(两个线程相互等待对方释放资源)
// 假设我们有一个银行账户类,并且存在以下情况
public class BankAccount {
private int balance;
// 两个同步方法,相互等待对方释放资源
public synchronized void deposit(int amount) throws InterruptedException {
if (amount > balance) {
System.out.println("Deposit: Amount=" + amount + ", Insufficient balance");
throw new InterruptedException(); // 在存款失败时抛出异常并中断线程
}
balance += amount;
System.out.println("Deposit: Amount=" + amount + ", Balance=" + balance);
}
public synchronized void withdraw(int amount) throws InterruptedException {
if (amount > balance) {
System.out.println("Withdrawal: Amount=" + amount + ", Insufficient balance");
throw new InterruptedException(); // 在取款失败时抛出异常并中断线程
}
balance -= amount;
System.out.println("Withdrawal: Amount=" + amount + ", Balance=" + balance);
}
}
在这个例子中,deposit(int amount)
和 withdraw(int amount)
两个方法都是同步的,它们会相互等待对方释放资源。这就可能导致死锁问题:两个线程互相等待对方释放资源,结果都陷入无限循环,无法继续执行。
要避免这种问题,可以采用以下策略:
- 设置超时时间:在尝试获取资源(如存款、取款)超过一定时间后,抛出异常并中断线程。这样可以减少死锁的可能。
- 使用无等待模式:某些并发框架或库提供了无等待模式,即当一个线程调用一个需要同步的资源方法时,不会阻塞当前线程,而是立即返回(通常是一个内部表示状态的对象)。
请根据实际情况选择合适的避免死锁的方法。
还没有评论,来说两句吧...