美好的一天!
我需要使用信号量来解决同步问题。我已经阅读了很多教程,我现在知道我应该使用一个发布方法并获取方法,但是,我不知道在代码中使用它们的位置。你可以帮助我或链接我一个有用的教程。 我有班级帐户:
public class Account {
protected double balance;
public synchronized void withdraw(double amount) {
this.balance = this.balance - amount;
}
public synchronized void deposit(double amount) {
this.balance = this.balance + amount;
}
}
我有两个主题:存款人:
public class Depositer extends Thread {
// deposits $10 a 10 million times
protected Account account;
public Depositer(Account a) {
account = a;
}
@Override
public void run() {
for(int i = 0; i < 10000000; i++) {
account.deposit(10);
}
}
}
和抽屉:
public class Withdrawer extends Thread {
// withdraws $10 a 10 million times
protected Account account;
public Withdrawer(Account a) {
account = a;
}
@Override
public void run() {
for(int i = 0; i < 1000; i++) {
account.withdraw(10);
}
}
}
这里是主要的:
public class AccountManager {
public static void main(String[] args) {
// TODO Auto-generated method stub
Account [] account = new Account[2];
Depositor [] deposit = new Depositor[2];
Withdrawer [] withdraw = new Withdrawer[2];
// The birth of 10 accounts
account[0] = new Account(1234,"Mike",1000);
account[1] = new Account(2345,"Adam",2000);
// The birth of 10 depositors
deposit[0] = new Depositor(account[0]);
deposit[1] = new Depositor(account[1]);
// The birth of 10 withdraws
withdraw[0] = new Withdrawer(account[0]);
withdraw[1] = new Withdrawer(account[1]);
for(int i=0; i<2; i++)
{
deposit[i].start();
withdraw[i].start();
}
for(int i=0; i<2; i++){
try {
deposit[i].join();
withdraw[i].join();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
答案 0 :(得分:0)
我不确定是否能正确发现你的问题,但我会试一试。
您的帐户类已经是线程安全的,因为您对提款和存款方法使用'synchronized'关键字。当调用'synchronized'方法时,它会锁定'this',因此任何两个'synchronized'方法永远不会同时运行一个'Account'实例。 但是,如果您希望能够读取一个帐户的余额,则应添加同步的访问者。在这种情况下,余额一次只能由一个线程读取,这可以通过使用'ReentrantReadWriteLock'来更改。以下是有关如何使用它的代码:
class Account {
private double balance;
private ReentrantReadWriteLock balanceLock = new ReentrantReadWriteLock();
public void withdraw(double amount) {
try {
balanceLock.writeLock().lock();
this.balance = this.balance - amount;
}
finally {
balanceLock.writeLock().unlock();
}
}
public void deposit(double amount) {
try {
balanceLock.writeLock().lock();
this.balance = this.balance + amount;
}
finally {
balanceLock.writeLock().unlock();
}
}
public double getBalance() {
try {
balanceLock.readLock().lock();
return this.balance;
}
finally {
balanceLock.readLock().unlock();
}
}
}
在这种情况下,多个线程一次可以读取余额,但一次只能有一个线程可以更改余额。
答案 1 :(得分:0)
在您的示例中使用semapahore可能如下所示:
import java.util.concurrent.Semaphore;
public class Account {
private Semaphore semaphore = new Semaphore(1);
private double balance = 0;
public void withdraw(double amount){
deposit(amount * -1);
}
public void deposit(double amount){
semaphore.acquireUninterruptibly();
balance += amount;
semaphore.release();
}
}
此示例在语义上与同步锁定非常相似,因为它为每个Account实例设置一个Semaphore(类似于可用于锁定对象实例的单个互斥锁)。它还不间断地(即永远地)等待获取许可证,类似于尝试获取对象锁定的引擎盖代码。如果你不想永远等待,你可以将你的impl改为:
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class Account {
private Semaphore semaphore = new Semaphore(1);
private double balance = 0;
public void withdraw(double amount){
deposit(amount * -1);
}
public void deposit(double amount){
try {
semaphore.tryAcquire(1, TimeUnit.SECONDS);
balance += amount;
semaphore.release();
}
catch (InterruptedException e) {
//Probably want to throw a more specific exception type here...
throw new RuntimeException("Timed out waiting for an account balance...");
}
}
}
在此示例中,您只需要1秒钟即可获得许可,如果没有,则抛出异常。