未同步:
Account.java(賬戶類)
package thread01;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Account {
private double balance;
private Lock accountLock=new ReentrantLock();
public double getBalance() {
return balance;
}
public void deposit(double money) {
double newBalance = balance + money;
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
balance = newBalance;
System.out.println("Account balance:"+balance);
}
}
AddMoneyThread.java(線程類)
package thread01;
public class AddMoneyThread implements Runnable {
private Account account;
private double money;
public AddMoneyThread(Account account, double money) {
this.account = account;
this.money = money;
}
@Override
public void run() {
account.deposit(money);
}
}
測試類
package thread01;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test01 {
public static void main(String[] args) {
Account account=new Account();
ExecutorService service=Executors.newFixedThreadPool(100);
for(int i=0;i<100;i++){
service.execute(new AddMoneyThread(account, 1));
}
service.shutdown();
while(!service.isTerminated()){}
System.out.println("賬戶余額:"+account.getBalance());
}
}
測試結(jié)果:2臭增,沒有同步
</br>
</br>
</br>
同步有三種方法
方法1:修改Account.java中deposit方法,添加修飾符synchronized
package thread01;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Account {
private double balance;
private Lock accountLock=new ReentrantLock();
public double getBalance() {
return balance;
}
public synchronized void deposit(double money) {
double newBalance = balance + money;
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
balance = newBalance;
System.out.println("Account balance:"+balance);
}
}
方法2:AddMoneyThread.java中添加synchronized塊
package thread01;
public class AddMoneyThread implements Runnable {
private Account account;
private double money;
public AddMoneyThread(Account account, double money) {
this.account = account;
this.money = money;
}
@Override
public void run() {
synchronized(account){
account.deposit(money);
}
}
}
方法3:Account.java湃累,添加lock機(jī)制
package thread01;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Account {
private double balance;
private Lock accountLock=new ReentrantLock();
public double getBalance() {
return balance;
}
public void deposit(double money) {
accountLock.lock();
try{
double newBalance = balance + money;
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
balance = newBalance;
}finally{
accountLock.unlock();
System.out.println("Account balance:"+balance);
}
}
}
面試題:簡述synchronized 和java.util.concurrent.locks.Lock的異同首懈?
答:Lock是Java 5以后引入的新的API菱农,和關(guān)鍵字synchronized相比
主要相同點(diǎn):Lock 能完成synchronized所實(shí)現(xiàn)的所有功能炕淮;
主要不同點(diǎn):Lock有比synchronized更精確的線程語義和更好的性能,而且不強(qiáng)制性的要求一定要獲得鎖干毅。synchronized會自動(dòng)釋放鎖宜猜,而Lock一定要求程序員手工釋放,并且最好在finally 塊中釋放(這是釋放外部資源的最好的地方)溶锭。