2016-09-21 3 views
0

Ich habe Probleme mit zwei Threads, die nicht richtig zu synchronisieren scheinen. Ich habe grundsätzlich einen booleschen Wertnamen "belegt". Es wird auf false gesetzt, wenn kein Thread gestartet wird. aber wenn man startet, sind die Thread-Sets belegt. Ich habe eine Klasse, die den Thread (run) hat und sie ruft die unten stehenden Funktionen auf.Multi-Thread Producer/Consumer Synchronisationsprobleme

Dies ist ein Scheinbankbeispiel, das einen Betrag (Anfangssaldo) aufnimmt und dann Abhebungen und Einzahlungen nach dem Zufallsprinzip ausführt. Mein Professor Erwähnung etwas über Signalisierung bilden den Rückzug Faden zum Pfand Gewinde? Wie funktioniert das? Der Rückzugfaden sollte laufen, bis das Guthaben zwei niedrig ist und auf einen Pfandfaden warten. Wie soll ich das machen?

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(); 


    } 
} 
+0

Probieren Sie eine BlockingQueue aus. –

Antwort

0

Zuerst müssen Sie Sie occupid Variable volatile markieren. Ohne dieses Schlüsselwort wird der Variablenwert in einem Thread in einem anderen nicht sichtbar.

Zweitens, Sie versuchen, externe Synchronisierungsrichtlinie für bank Einheit zu implementieren. Solch eine Idee ist im Grunde nicht gut: Wenn jemand dieselbe bank ohne korrekte Synchronisation verwendet, bricht es den internen Bankstatus. Es ist besser, die interne Synchronisierungsrichtlinie zu implementieren und es der Bank zu ermöglichen, ihren Status selbst zu überwachen.

z. die API von Bank Klasse automatisch laufenden Bankbetrieb Finishing Mit diesem Design interner Bank Zustand immer konsistent und alleBank User werden warten wie diese

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

sein.

+0

Danke für den Tipp. –

+1

Er braucht nicht 'synchronisiert', er benutzt' Locks'. Er benutzt sie nur falsch. – Kayaman

+0

@Kayaman Eigentlich benötigt er keine Locks in Action-Klasse. Das ganze Design ist nicht gut, was ich sage und vorgeschlagen besser und einfacheres Design –

4

Ihre Lock und Condition Verwendung ist falsch. Sie rufen lock() an, ohne dass Sie unlock() anrufen, und Sie rufen signal() an, ohne dass jemand await() angerufen hat.

Siehe die documentation für ein Beispiel sehr viel ähnliche zu Ihrem Problem.