Threads Lock über mehrere Abschnitte in verschiedenen Methoden

Moin,
ich habe das folgende Problem mit Locks:

Ich habe mehrere Methoden und wenn ein kritischer Abschnitt in Methode a() erreicht wird, dann muss auch gleichzeitig ein kritischer Abschnitt in Methode b() "scharf gestellt" werden.
Umgekehrt gilt dies aber nicht!

Ich probiere es am Beispiel deutlich zu machen:

Java:
private static volatile char[]	accectableChars;

public char[] getAccectableChars()
{
    // start passiv-kritischer Bereich
    ...
    // end passiv-kritischer Bereich
   
    return accectableChars;
}

public void setAccectableChars(char[] accectableChars)
{
    // start aktiv-kritischer Bereich
	accectableChars = accectableChars;
    // end aktiv-kritischer Bereich
}
Wenn die set Methode aufgerufen wird, dürfen andere Threads auch nicht auf die get-Methode zugreifen. Wenn aber kein Thread in der set-Methode ist, sollen sie alle parallel auf die get zugreifen.

Meine nicht korrekte Lösung nutzt ein ReentrantLock-Objekt, das in set aktiviert wird und in get mit isLocked() abgefragt wird:

Java:
private final ReentrantLock setCharLock;
private static volatile char[]	accectableChars;

public char[] getAccectableChars()
{
    while(setCharLock.isLocked())
    {
			
    }
    // start passiv-kritischer Bereich
       ...
    // end passiv-kritischer Bereich
		
    return accectableChars;
}

public void setAccectableChars(char[] accectableChars)
{
    // start aktiv-kritischer Bereich
    setCharLock.lock();
		
    accectableChars = accectableChars;

    // end aktiv-kritischer Bereich
    setCharLock.unlock();
}
Mit dieser "Lösung" kann das Problem auftreten, dass Thread 1 im passiv-kritischen Bereich ist, wenn Thread2 den aktiv-kritischen Bereich locked, da Thread1 nur vor dem passiv kritischen Bereich testet, ob der Lock gesetzt ist, er müsste es aber während des ganzen Abschnitts tun und jeder andere Thread müsste mit dem Betreten des aktiv-kritischen Abschnitts warten, bis alle Threads aus dem passiv-kritischen raus sind.

Wie löst man das am saubersten?
 
Sofern du in jeder Methode nur ein einziges mal auf accectableChars zugreifst benötigst du gar keinen Lock. Die Variable als volatile zu deklarieren reicht aus.
Falls du aber doch Locks benötigen solltest, was mit ziemlicher Sicherheit hier nicht der Fall ist, musst du halt auch in getAccectableChars den Lock aktivieren.
acceptable wird übrigens mit p geschrieben.
 
Zuletzt bearbeitet:
Hallo DrZoidberg,
danke für die Antwort. Mein Beispiel war nicht nur orthografisch schlecht gewählt. Ich habe n der set-Methode die Pünktchen weggelassen, in der Realität soll das char-Array eingelesen, verändert und neu gespeichert werden. Z. B. so:
Java:
public void setAccectableChars(char[] accectableCharsLocal)
{
    // start aktiv-kritischer Bereich
    setCharLock.lock();

    for(int i = 0; i < accectableCharsLocal.length; i++)
    {
	AccectableChars.accectableChars[i] = accectableCharsLocal[i] * 2;		
    }

    // end aktiv-kritischer Bereich
    setCharLock.unlock();
}
Jetzt brauch ich natürlich den Lock auch in der get-Methode, nicht dass das statische Array zur Hälfte erneuert ist, wenn es von einem anderen Thread gelesen wird. Da die get-Methode zur set-Methode im Verhältnis 50000:1 aufgerufen wird, ist es aus Performance-Sicht ein Unding, beide generell zu locken. Anscheinend gibt es aber bisher keine andere Möglichkeit, oder?
 
So ganz komplett verstehe ich dich nicht..

Es gibt die Klasse ReentrantReadWriteLock, die mir geeignet scheint.

Hier kannst du über readLock() bzw. writeLock() entscheiden, welche Art von Lock du benötigst. Dabei blockiert ein Writer "natürlich" alle Reader.
 
Ich würde jedes mal ein neues char Array erstellen.
Java:
public void setAccectableChars(char[] accectableCharsLocal)
{
    char[] newChars = new char[accectableCharsLocal.length];
    for(int i = 0; i < accectableCharsLocal.length; i++)
    {
        newChars[i] = accectableCharsLocal[i] * 2;       
    }
    
    AccectableChars.accectableChars = newChars;
}

Wobei ich jetzt natürlich den Rest des Codes kennen müsste um beurteilen zu können ob das wirklich Thread sicher ist.
Aber der Punkt ist, dass man häufig Locks vermeiden kann, wenn man Datenstrukturen (in diesem Fall ein Array) nicht verändert, sondern neu erstellt.
 

Zurück
Oben