Java并发编程问题:锁竞争和死锁实例
锁竞争和死锁是Java并发编程中常见的两个问题。下面我将分别给出实例解释。
锁竞争(Race Condition):
这种情况通常发生在多个线程同时访问共享资源,而这些资源的访问又涉及到锁操作时,可能出现的错误结果。
例如:class Counter {
private int count = 0;
public synchronized void increment() {
count++;
notifyAll(); // 唤醒所有等待的线程
}
public synchronized int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
counter.increment(); // 假设这里的操作是正确的
try { // 为了模拟可能的等待情况
wait(100); // 模拟线程在资源竞争中等待的情况
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}));
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
counter.increment(); // 这里操作错误,可能导致count不增加
try { // 同样模拟等待情况
wait(100); // 线程在资源竞争中等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}));
thread1.start(); // 启动线程1,先进行资源访问操作
thread2.start(); // 同时启动线程2,错误操作可能在后启动的线程中发生
这个例子展示了锁竞争可能导致的结果不一致。为了避免死锁,开发者通常需要遵循适当的并发控制策略。
死锁(Deadlock):
死锁是两个或更多的线程在执行过程中,因争夺资源而造成的一种相互等待的现象,且在这种现象中没有任何线程能够推进其执行。例如:
class Bank {
private Map<String, Account> accounts = new HashMap<>();
public synchronized void openAccount(String owner) {
Account account = new Account(owner);
if (accounts.containsKey(owner)) { // 冲突,存在多个账户归属同一个拥有者
throw new IllegalArgumentException("Account for " + owner + " already exists.");
} else {
accounts.put(owner, account);
}
}
public synchronized Account getAccount(String owner) {
return accounts.get(owner);
}
}
class Account {
private String owner;
public Account(String owner) {
this.owner = owner;
}
public String getOwner() {
return owner;
}
}
public class Main {
public static void main(String[] args) {
Bank bank = new Bank();
Thread thread1 = new Thread(() -> {
bank.openAccount("User1"); // 创建账户
try { // 模拟线程等待资源
wait(500); // 线程在等待银行账户创建完成时发生等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
Thread thread2 = new Thread(() -> {
bank.openAccount("User2"); // 冲突,试图创建已经被其他线程占用的账户
try { // 与线程1类似,模拟线程等待资源冲突发生
wait(500); // 线程在等待银行账户创建完成时发生等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
thread1.start(); // 启动创建第一个用户账户的线程
thread2.start(); // 同时启动尝试创建第二个用户账户,但已由线程1占用的线程
这个例子展示了死锁可能的情况。两个线程同时对银行资源进行访问,当一个线程在获取资源后等待另一个线程释放资源时,如果这时又有线程试图获取已被其他线程占用的资源,就会导致所有线程都无法推进执行,从而形成死锁。
还没有评论,来说两句吧...