使用java.util.concurrent.locks.ReentrantLock库,如下所示:
两个线程生成一个随机数,并使用它来更新存储在类Account中的共享变量account1和account2 - 一个锁用于保护写入共享变量
package osproj221;
import java.util.concurrent.locks.ReentrantLock;
public class Accounts {
private int account1,account2;
private final ReentrantLock mutex;
public Accounts(){
account1=account2=0;
mutex = new ReentrantLock();
}
public void updateAccounts(int amt){
try{
mutex.lock();
account1 += amt;
account2 -= amt;
}catch(Exception ex){
System.out.println(ex);
}finally{mutex.unlock();}
}
public int getAccount1(){
return this.account1;
}
public int getAccount2(){
return this.account2;
}
}
我的线程实现了Runnable接口,如下所示:
package osproj221;
import java.util.Random;
public class RaceThread implements Runnable {
private Random myRand = new Random();
private int counter = 0;
private Accounts accounts;
public RaceThread(Accounts accounts){
this.accounts = accounts;
}
public void run(){
do{
int r = myRand.nextInt(300);
r = Math.abs(r);
accounts.updateAccounts(r);
counter++;
}while((accounts.getAccount1() + accounts.getAccount2() == 0));
System.out.println(counter + " " + accounts.getAccount1() + " " + accounts.getAccount2());
}
}
最后是我的主课
package osproj221;
public class Main {
public static void main(String[] args) {
Accounts myAccounts = new Accounts();
Thread t1 = new Thread(new RaceThread(myAccounts));
Thread t2 = new Thread(new RaceThread(myAccounts));
t1.start();
t2.start();
try{
t1.join();
t2.join();
}catch(Exception ex){
System.out.println(ex);
}
System.out.println(myAccounts.getAccount1() + " " + myAccounts.getAccount2());
}
}
看起来比我想象的要长一点 - 道歉。我希望这两个线程都不会终止,因为当互斥锁处理保护account1和account2的更新时,account1 + account2应该总是= 0。似乎发生的是其中一个线程退出,因为它失败了account1 + account2 == 0条件,而另一个线程无限期地继续。我很困惑!
答案 0 :(得分:4)
这是因为你没有锁定吸气剂上的读数。这意味着线程2可以读取处于不一致状态的数据,而线程1正在更新数据(在+ =和 - =之间)。 问题可能发生如下:
主题1:
主题2:
主题1:
解决方案: 不幸的是,你不能单独同步你的getter我会改为推荐一个新的get方法:
public int getAccountsSum() {
try {
mutex.lock();
return this.account1 + this.account2;
} finally { mutex.unlock(); }
并在RaceThread.run()
中将while条件更改为:
}while((accounts.getAccountsSum() == 0));
答案 1 :(得分:1)
同步你的写作是不够的;您还需要使用相同的锁定/监视器同步您的读取。
如果不这样做,可能会发生不好的事情:
account1
和新值account2
,反之亦然。答案 2 :(得分:1)
您只是在同步对变量的写访问权。
因此,有一个线程将帐户1设置为新值而另一个线程正在读取旧帐户2。
答案 3 :(得分:0)
你的Getters没有被锁定。因此,即使您使用互斥锁进行更新,其他线程也会调用可以解锁的Getters。
public int getAccounts(){ int result = 0; 尝试{ mutex.lock(); result = account1 + account2; } catch(Exception ex){ 的System.out.println(前); 最后} {mutex.unlock();} 返回结果; }