死锁的产生必要4条件:
- 互斥,共享资源 X 和 Y 只能被一个线程占用;
- 占有且等待,线程 T1 已经取得共享资源 X,在等待共享资源 Y 的时候,不释放共享资源 X;
- 不可抢占,其他线程不能强行抢占线程 T1 占有的资源;
- 循环等待,线程 T1 等待线程 T2 占有的资源,线程 T2 等待线程 T1 占有的资源,就是循环等待
以执行main方法后 产生死锁
@Data
@AllArgsConstructor
public class Account {
private String accountName;
private int balance;
//更新转出方的余额
public void debit(int amount) {
this.balance -= amount;
}
//更新转入方的余额
public void credit(int amount) {
this.balance += amount;
}
}
public class TransferAccount implements Runnable {
//转出账户
private Account fromAccount;
//转入账户
private Account toAccount;
//转账金额
private int amount;
public TransferAccount(Account fromAccount, Account toAccount, int amount) {
this.fromAccount = fromAccount;
this.toAccount = toAccount;
this.amount = amount;
}
@Override
public void run() {
while (true) {
synchronized (fromAccount) {
synchronized (toAccount) {
if (fromAccount.getBalance() >= amount) {
fromAccount.debit(amount);
toAccount.credit(amount);
}
}
}
//转出账户的余额
System.out.println(fromAccount.getAccountName() + "->" + fromAccount.getBalance());
//转入账户的余额
System.out.println(toAccount.getAccountName() + "->" + toAccount.getBalance());
}
}
public static void main(String[] args) {
Account fromAccount = new Account("用户A", 500000);
Account toAccount = new Account("用户B", 500000);
Thread a = new Thread(new TransferAccount(fromAccount, toAccount, 100));
Thread b = new Thread(new TransferAccount(toAccount, fromAccount, 300));
a.start();
b.start();
}
}
解决死锁问题:
破坏以上其中一个条件
- 互斥 此条件无法破坏
- 占有且等待:破坏此条件, 在一个变量中统一分配资源X和Y
- 不可抢占:破坏此条件用ReentrantLock
- 循环等待:破坏此条件
- 占有且等待:破坏此条件
public class Allocator {
private List<Object> list=new ArrayList<>();
synchronized boolean apply(Object from,Object to){
if(list.contains(from)||list.contains(to)){
return false;
}
list.add(from);
list.add(to);
return true;
}
synchronized void free(Object from,Object to){
list.remove(from);
list.remove(to);
}
}
public class TransferAccount01 implements Runnable{
//转出账户
private Account fromAccount;
//转入账户
private Account toAccount;
//转账金额
private int amount;
//资源分配者对象
Allocator allocator;
public TransferAccount01(Account fromAccount, Account toAccount, int amount, Allocator allocator) {
this.fromAccount = fromAccount;
this.toAccount = toAccount;
this.amount = amount;
this.allocator=allocator;
}
@Override
public void run() {
while(true){
if(allocator.apply(fromAccount,toAccount)) {
try {
synchronized (fromAccount) {
synchronized (toAccount) {
if (fromAccount.getBalance() >= amount) {
fromAccount.debit(amount);
toAccount.credit(amount);
}
}
}
//转出账户的余额
System.out.println(fromAccount.getAccountName() + "->" + fromAccount.getBalance());
//转入账户的余额
System.out.println(toAccount.getAccountName() + "->" + toAccount.getBalance());
}finally {
//释放
allocator.free(fromAccount,toAccount);
}
}
}
}
public static void main(String[] args) {
Account fromAccount=new Account("用户A",500000);
Account toAccount=new Account("用户B",500000);
Allocator allocator=new Allocator();
Thread a =new Thread(new TransferAccount01(fromAccount,toAccount,100,allocator));
Thread b=new Thread(new TransferAccount01(toAccount,fromAccount,300,allocator));
a.start();
b.start();
}
}
Thread.join
例:main 线程调用了 t1.join()
当前main线程被阻塞wait 当t1线程执行完后 唤醒阻塞状态的main线程
阻塞当前线程,执行完后 唤醒
ThreadLocal原理
线程隔离机制
数组下标: key的生成机制–>斐波那契数列