多线程同步方法

xiaoxiao2021-02-27  373

偶然间在今日头条里面看到一个java的面试题,描述如下:

一个银行里面有N个账户,一开始每个账户都有一定的资金,账户与账户之间可以转移资金,分别给出不同步和同步下的资金转移程序

一、不同步情况下:

不同步下产生的结果是账户总的资金会产生变化,比如:线程1将a账户转移100到b账户中,转移结束后,线程1被等待,这时线程2将a账户转移100到b账户,在转移过程中线程1被唤醒并执行了计算总资金的操作,那么此时总的资金就出问题了。

package com.java.thread; public abstract class Bank { public abstract void transfer(int from, int to, double amount) throws InterruptedException; public abstract double getTotalBalance(); public abstract int size(); } package com.java.thread; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class BankUnsynch extends Bank { private double[] accounts; //private Lock bankLock; //private Condition sufficientFunds; public BankUnsynch(int n, double initBalance) { accounts = new double[n]; //Arrays.fill(accounts, initBalance); for(int i = 0; i < accounts.length; i++){ accounts[i] = initBalance; } //bankLock = new ReentrantLock(); //sufficientFunds = bankLock.newCondition(); } @Override public void transfer(int from, int to, double amount) throws InterruptedException { //bankLock.lock(); try{ if(accounts[from] < amount){ //sufficientFunds.await(); //wait(); return; } System.out.println(Thread.currentThread()); accounts[from] -= amount; System.out.println(amount + " from " + from + " to " + to); accounts[to] += amount; System.out.println("totalBalance is " + getTotalBalance()); //notifyAll(); //sufficientFunds.signalAll(); }finally{ //bankLock.unlock(); } } @Override public double getTotalBalance() { //bankLock.lock(); try{ double sum = 0d; for(int i = 0; i < accounts.length; i++){ sum += accounts[i]; } return Math.round(sum * 100) / 100; }finally{ //bankLock.unlock(); } } @Override public int size() { return accounts.length; } } package com.java.thread; public class MRunnable implements Runnable { private Bank bank; private int fromAccount; private double maxBalance; private int DELAY = 10; public MRunnable(Bank bank, int fromAccount, double maxBalance) { this.bank = bank; this.fromAccount = fromAccount; this.maxBalance = maxBalance; } @Override public void run() { try{ while(true){ int toAccount = (int)(bank.size() * Math.random()); double amount = Math.round(maxBalance * Math.random()); bank.transfer(fromAccount, toAccount, amount); Thread.sleep((int) (DELAY * Math.random())); } }catch(InterruptedException e){ e.printStackTrace(); } } } package com.java.thread; public class BankTest { public static final int NACCOUNTS = 100; public static final double INITIAL_BALANCE = 1000; public static void main(String[] args) { Bank bank = new BankUnsynch(NACCOUNTS, INITIAL_BALANCE); for(int i = 0; i < NACCOUNTS; i++){ MRunnable r = new MRunnable(bank, i, INITIAL_BALANCE); Thread t = new Thread(r); t.start(); } } }

二、Lock/Condition同步方式

package com.java.thread; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class BankUnsynch extends Bank { private double[] accounts; private Lock bankLock; private Condition sufficientFunds; public BankUnsynch(int n, double initBalance) { accounts = new double[n]; //Arrays.fill(accounts, initBalance); for(int i = 0; i < accounts.length; i++){ accounts[i] = initBalance; } bankLock = new ReentrantLock(); sufficientFunds = bankLock.newCondition(); } @Override public void transfer(int from, int to, double amount) throws InterruptedException { bankLock.lock(); try{ if(accounts[from] < amount){ sufficientFunds.await(); //wait(); return; } System.out.println(Thread.currentThread()); accounts[from] -= amount; System.out.println(amount + " from " + from + " to " + to); accounts[to] += amount; System.out.println("totalBalance is " + getTotalBalance()); //notifyAll(); sufficientFunds.signalAll(); }finally{ bankLock.unlock(); } } @Override public double getTotalBalance() { bankLock.lock(); try{ double sum = 0d; for(int i = 0; i < accounts.length; i++){ sum += accounts[i]; } return Math.round(sum * 100) / 100; }finally{ bankLock.unlock(); } } @Override public int size() { return accounts.length; } }

三、scynchronized同步方式

package com.java.thread; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class BankUnsynch extends Bank { private double[] accounts; //private Lock bankLock; //private Condition sufficientFunds; public BankUnsynch(int n, double initBalance) { accounts = new double[n]; //Arrays.fill(accounts, initBalance); for(int i = 0; i < accounts.length; i++){ accounts[i] = initBalance; } //bankLock = new ReentrantLock(); //sufficientFunds = bankLock.newCondition(); } @Override public synchronized void transfer(int from, int to, double amount) throws InterruptedException { //bankLock.lock(); try{ while(accounts[from] < amount){ //sufficientFunds.await(); wait(); return; } System.out.println(Thread.currentThread()); accounts[from] -= amount; System.out.println(amount + " from " + from + " to " + to); accounts[to] += amount; System.out.println("totalBalance is " + getTotalBalance()); notifyAll(); //sufficientFunds.signalAll(); }finally{ //bankLock.unlock(); } } @Override public synchronized double getTotalBalance() { //bankLock.lock(); try{ double sum = 0d; for(int i = 0; i < accounts.length; i++){ sum += accounts[i]; } return Math.round(sum * 100) / 100; }finally{ //bankLock.unlock(); } } @Override public int size() { return accounts.length; } }

两种同步方式的总结:http://blog.csdn.net/fw0124/article/details/6672522

转载请注明原文地址: https://www.6miu.com/read-3598.html

最新回复(0)