多线程生产者/消费者同步问题

时间:2016-09-21 15:08:05

标签: java multithreading synchronization producer-consumer

我遇到两个似乎没有正确同步的线程的问题。我基本上有一个布尔值名称“被占用”。没有线程启动时设置为false。但是当一个人开始时,线程集被占用是真的我有一个有线程(运行)的类,他们调用下面的函数。

这是一个模拟银行示例,它接受金额(初始余额),然后随机执行提款和存款。我的教授提到了一些关于信号形成退出线程到存款线程的信息?这是如何运作的?撤销线程,它应该运行,直到余额为两个低并等待存款线程。我该怎么做?

   package bank;

import java.util.Random;
import bank.Bank;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.Condition;

/**
 *
 * @author KJ4CC
 */
public class Action {

    private Lock accessLock = new ReentrantLock();
    private Condition cond = accessLock.newCondition();
    //private Condition withdraw  = accessLock.newCondition();


    Random rand = new Random();
    Object lock = new Object();
    Bank getBalance = new Bank();

    public void widthdrawl(int threadNum) throws InterruptedException {
        int amount = rand.nextInt(50);
            accessLock.lock();

            if (getBalance.getbalance() > amount) {

                getBalance.setBalance(getBalance.getbalance() - amount);

                System.out.println("\t\t\tThread " + threadNum + " withdrawls " + amount + "\t Balance is " + getBalance.getbalance());

            } else {

                System.out.println("\t\t\tThread " + threadNum + " Failed to withdrawl " + amount + "\t Balance is " + getBalance.getbalance());
                cond.await();

            }


            accessLock.unlock();
            Thread.sleep(rand.nextInt(5));

    }

    public void deposit(int threadNum) throws InterruptedException {
        int amount = rand.nextInt(200);
        accessLock.lock();


            getBalance.setBalance(getBalance.getbalance() + amount);
            System.out.println("Thread " + threadNum + " Deposits " + amount + "\t\t\t\t Balance is " + getBalance.getbalance());
            Thread.sleep(rand.nextInt(100));

            cond.signal();
            accessLock.unlock();


    }
}

2 个答案:

答案 0 :(得分:4)

您的LockCondition用法错误。您在没有在任何地方拨打lock()的情况下呼叫unlock(),并且在没有任何人呼叫signal()的情况下您正在呼叫await()

请参阅documentation,了解您的问题的非常相关

答案 1 :(得分:0)

首先,您必须标记occupid变量volatile。如果没有此关键字,则更改一个线程中的变量值将无法在另一个线程中显示。

其次,您尝试为bank实体实施外部同步策略。这样的想法基本上并不好:如果有人在没有正确同步的情况下使用相同的bank,它就会打破内部银行状态。最好实施内部同步策略并允许银行自行保护其状态。

E.g。 Bank类的API可能就像这样

class Bank {
   double synchronize getBalance() { ... }
   void synchronize deposit(double amount) { ... }
   void synchronize widthdrawl(double amount) throw BankException { ... }
}

使用此设计,内部Bank状态始终保持一致,任何 Bank用户将等待自动完成当前银行操作。