Note 1: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Cloze
GUID: &{f,XLC*~+
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Hashfunktion (Annahmen)Falls die Elemente in \(D\) gross sind und Speicherzugriffe sowie Vergleiche teuer sind, verwendet man eine
Hashfunktion \(h : U \to [m]\) mit zwei Eigenschaften:
- \(h\) ist effizient berechenbar
- {{c2::\(h\) verhält sich wie eine Zufallsfunktion: \(\forall u \in U\;\forall i \in [m]:\; \Pr[h(u) = i] = \tfrac{1}{m}\), unabhängig für verschiedene \(u\)}}
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Hashfunktion (Annahmen)Falls die Elemente in \(D\) gross sind und Speicherzugriffe sowie Vergleiche teuer sind, verwendet man eine
Hashfunktion \(h : U \to [m]\) mit zwei Eigenschaften:
- \(h\) ist effizient berechenbar
- {{c2::\(h\) verhält sich wie eine Zufallsfunktion: \(\forall u \in U\;\forall i \in [m]:\; \Pr[h(u) = i] = \tfrac{1}{m}\), unabhängig für verschiedene \(u\)}}
\(U\) ist das Universum der möglichen Element-Werte; \([m] = \{1, \ldots, m\}\) sind die Hash-Werte.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Hashfunktion (Annahmen)</b><br>Falls die Elemente in \(D\) gross sind und Speicherzugriffe sowie Vergleiche teuer sind, verwendet man eine <b>Hashfunktion</b> \(h : U \to [m]\) mit zwei Eigenschaften:<br><ul><li>{{c1::\(h\) ist effizient berechenbar}}</li><li>{{c2::\(h\) verhält sich wie eine Zufallsfunktion: \(\forall u \in U\;\forall i \in [m]:\; \Pr[h(u) = i] = \tfrac{1}{m}\), unabhängig für verschiedene \(u\)}}</li></ul> |
| Extra |
|
\(U\) ist das Universum der möglichen Element-Werte; \([m] = \{1, \ldots, m\}\) sind die Hash-Werte. |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Note 2: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Cloze
GUID: ){U0btIv-;
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Floyd's Cycle Finding (Schlüsseleigenschaft)
Definiere die Folge \(x_0 := n,\; x_i := a[x_{i-1}]\) für \(i \geq 1\). Sei der Pfad \(k \geq 1\) Kanten lang und der Kreis \(\ell \geq 3\) Kanten lang.
Wähle \(0 \leq r < \ell\) und \(s \geq 1\) mit \(k + r = s\ell\). Dann gilt:\[x_{k+r} = {{c2::x_{2(k+r)} }}.\]Insbesondere existiert ein {{c3::\(i \leq n\) mit \(x_i = x_{2i}\)}}.
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Floyd's Cycle Finding (Schlüsseleigenschaft)
Definiere die Folge \(x_0 := n,\; x_i := a[x_{i-1}]\) für \(i \geq 1\). Sei der Pfad \(k \geq 1\) Kanten lang und der Kreis \(\ell \geq 3\) Kanten lang.
Wähle \(0 \leq r < \ell\) und \(s \geq 1\) mit \(k + r = s\ell\). Dann gilt:\[x_{k+r} = {{c2::x_{2(k+r)} }}.\]Insbesondere existiert ein {{c3::\(i \leq n\) mit \(x_i = x_{2i}\)}}.
Anschauung: Sobald die Folge \(x_0, x_1, \ldots\) den Kreis erreicht hat (nach \(k\) Schritten), läuft sie unendlich im Kreis. Wir suchen einen Schritt-Index \(i\), bei dem ein einfach-laufender und ein doppelt-laufender Pointer den gleichen Knoten betreten. Dafür muss \(2i - i = i\) ein Vielfaches der Kreislänge \(\ell\) sein und \(i \geq k\) gelten: also \(i = k + r\) mit \(k + r \equiv 0 \pmod{\ell}\).
Wahl: \(s = 1\) für \(k \leq \ell\), und \(s = \lceil k/\ell \rceil\) für \(k > \ell\).
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Floyd's Cycle Finding (Schlüsseleigenschaft)</b><br>Definiere die Folge \(x_0 := n,\; x_i := a[x_{i-1}]\) für \(i \geq 1\). Sei der Pfad \(k \geq 1\) Kanten lang und der Kreis \(\ell \geq 3\) Kanten lang.<br>Wähle \(0 \leq r < \ell\) und \(s \geq 1\) mit {{c1::\(k + r = s\ell\)}}. Dann gilt:\[x_{k+r} = {{c2::x_{2(k+r)} }}.\]Insbesondere existiert ein {{c3::\(i \leq n\) mit \(x_i = x_{2i}\)}}. |
| Extra |
|
Anschauung: Sobald die Folge \(x_0, x_1, \ldots\) den Kreis erreicht hat (nach \(k\) Schritten), läuft sie unendlich im Kreis. Wir suchen einen Schritt-Index \(i\), bei dem ein einfach-laufender und ein doppelt-laufender Pointer den gleichen Knoten betreten. Dafür muss \(2i - i = i\) ein Vielfaches der Kreislänge \(\ell\) sein und \(i \geq k\) gelten: also \(i = k + r\) mit \(k + r \equiv 0 \pmod{\ell}\).<br><br>Wahl: \(s = 1\) für \(k \leq \ell\), und \(s = \lceil k/\ell \rceil\) für \(k > \ell\). |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Note 3: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Cloze
GUID: +N@/D$lVm_
modified
Before
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::2._Sortieren_und_Selektieren
Selektionsproblem: Bestimme in einer Folge \((A[1], \ldots, A[n])\) paarweise verschiedener Zahlen den
\(k\)-kleinsten Wert.
Naiver Ansatz: Sortieren + Index, Laufzeit
\(O(n \log n)\).
Schneller geht es mit
QuickSelect (erwartet
\(O(n)\)):
QuickSelect(A, ℓ, r, k):
p ← Uniform({ℓ, ℓ+1, ..., r})
t ← Partition(A, ℓ, r, p)
if t = ℓ + k - 1: return A[t] # gefunden
else if t > ℓ + k - 1:
return QuickSelect(A, ℓ, t-1, k) # links
else:
return QuickSelect(A, t+1, r, k - t) # rechts
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::2._Sortieren_und_Selektieren
Selektionsproblem: Bestimme in einer Folge \((A[1], \ldots, A[n])\) paarweise verschiedener Zahlen den
\(k\)-kleinsten Wert.
Naiver Ansatz: Sortieren + Index, Laufzeit
\(O(n \log n)\).
Schneller geht es mit
QuickSelect (erwartet
\(O(n)\)):
QuickSelect(A, ℓ, r, k):
p ← Uniform({ℓ, ℓ+1, ..., r})
t ← Partition(A, ℓ, r, p)
if t = ℓ + k - 1: return A[t] # gefunden
else if t > ℓ + k - 1:
return QuickSelect(A, ℓ, t-1, k) # links
else:
return QuickSelect(A, t+1, r, k - t) # rechts
Im Gegensatz zu QuickSort rekursiert QuickSelect nur in eine der beiden Hälften (oder gibt direkt zurück, falls Pivot bereits an der gesuchten Position liegt). Das macht den Unterschied zwischen \(O(n \log n)\) und \(O(n)\) erwartet.
Bei einem Aufruf von QuickSelect ist die Anzahl Vergleiche \(T = \sum_{i=1}^{N} (r_i - \ell_i)\), wobei \(N\) die Anzahl Partition-Aufrufe ist.
After
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::2._Sortieren_und_Selektieren
Selektionsproblem: Bestimme in einer Folge \((A[1], \ldots, A[n])\) paarweise verschiedener Zahlen den
\(k\)-kleinsten Wert.
Naiver Ansatz: Sortieren + Index, Laufzeit
\(O(n \log n)\).
Schneller geht es mit
QuickSelect (erwartet \(O(
n)\)):
QuickSelect(A, ℓ, r, k):
p ← Uniform({ℓ, ℓ+1, ..., r})
t ← Partition(A, ℓ, r, p)
if t = ℓ + k - 1: return A[t] # gefunden
else if t > ℓ + k - 1:
return QuickSelect(A, ℓ, t-1, k) # links
else:
return QuickSelect(A, t+1, r, k - t) # rechts
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::2._Sortieren_und_Selektieren
Selektionsproblem: Bestimme in einer Folge \((A[1], \ldots, A[n])\) paarweise verschiedener Zahlen den
\(k\)-kleinsten Wert.
Naiver Ansatz: Sortieren + Index, Laufzeit
\(O(n \log n)\).
Schneller geht es mit
QuickSelect (erwartet \(O(
n)\)):
QuickSelect(A, ℓ, r, k):
p ← Uniform({ℓ, ℓ+1, ..., r})
t ← Partition(A, ℓ, r, p)
if t = ℓ + k - 1: return A[t] # gefunden
else if t > ℓ + k - 1:
return QuickSelect(A, ℓ, t-1, k) # links
else:
return QuickSelect(A, t+1, r, k - t) # rechts
Im Gegensatz zu QuickSort rekursiert QuickSelect nur in eine der beiden Hälften (oder gibt direkt zurück, falls Pivot bereits an der gesuchten Position liegt). Das macht den Unterschied zwischen \(O(n \log n)\) und \(O(n)\) erwartet.
Bei einem Aufruf von QuickSelect ist die Anzahl Vergleiche \(T = \sum_{i=1}^{N} (r_i - \ell_i)\), wobei \(N\) die Anzahl Partition-Aufrufe ist.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
<b>Selektionsproblem:</b> Bestimme in einer Folge \((A[1], \ldots, A[n])\) paarweise verschiedener Zahlen den {{c1::\(k\)-kleinsten Wert}}.<br><br>Naiver Ansatz: Sortieren + Index, Laufzeit {{c2::\(O(n \log n)\)}}.<br><br>Schneller geht es mit <b>QuickSelect</b> (erwartet {{c3::\(O(n)\)}}):<pre>QuickSelect(A, ℓ, r, k):
p ← Uniform({ℓ, ℓ+1, ..., r})
t ← Partition(A, ℓ, r, p)
if t = ℓ + k - 1: return A[t] # gefunden
else if t > ℓ + k - 1:
return QuickSelect(A, ℓ, t-1, k) # links
else:
return QuickSelect(A, t+1, r, k - t) # rechts</pre> |
<b>Selektionsproblem:</b> Bestimme in einer Folge \((A[1], \ldots, A[n])\) paarweise verschiedener Zahlen den {{c1::\(k\)-kleinsten Wert}}.<br><br>Naiver Ansatz: Sortieren + Index, Laufzeit {{c2::\(O(n \log n)\)}}.<br><br>Schneller geht es mit <b>QuickSelect</b> (erwartet \(O({{c3::n}})\)):<pre>QuickSelect(A, ℓ, r, k):
p ← Uniform({ℓ, ℓ+1, ..., r})
t ← Partition(A, ℓ, r, p)
if t = ℓ + k - 1: return A[t] # gefunden
else if t > ℓ + k - 1:
return QuickSelect(A, ℓ, t-1, k) # links
else:
return QuickSelect(A, t+1, r, k - t) # rechts</pre> |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::2._Sortieren_und_Selektieren
Note 4: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Classic
GUID: ,*ESus}q*l
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Floyd's Cycle Finding (Phase 1)
Wie wird mit nur drei Variablen ein \(i \geq 1\) mit \(x_i = x_{2i}\) berechnet, und welche Bedeutung hat das gefundene \(i\)?
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Floyd's Cycle Finding (Phase 1)
Wie wird mit nur drei Variablen ein \(i \geq 1\) mit \(x_i = x_{2i}\) berechnet, und welche Bedeutung hat das gefundene \(i\)?
igel := a[n]
hase := a[a[n]]
i := 1
while (igel != hase):
igel := a[igel]
hase := a[a[hase]]
i := i + 1Der Igel macht pro Iteration einen Schritt, der Hase zwei. Treffen sie sich, gilt \(x_i = x_{2i}\) mit \(i = k + r\) (Pfadlänge \(k\) plus Rest \(r\) wie in der Schlüsseleigenschaft).
Laufzeit: \(O(n)\), denn \(i \leq k + \ell \leq n\).
Field-by-field Comparison
| Field |
Before |
After |
| Front |
|
<b>Floyd's Cycle Finding (Phase 1)</b><br>Wie wird mit nur drei Variablen ein \(i \geq 1\) mit \(x_i = x_{2i}\) berechnet, und welche Bedeutung hat das gefundene \(i\)? |
| Back |
|
<pre>igel := a[n]
hase := a[a[n]]
i := 1
while (igel != hase):
igel := a[igel]
hase := a[a[hase]]
i := i + 1</pre>Der Igel macht pro Iteration einen Schritt, der Hase zwei. Treffen sie sich, gilt \(x_i = x_{2i}\) mit \(i = k + r\) (Pfadlänge \(k\) plus Rest \(r\) wie in der Schlüsseleigenschaft).<br><br>Laufzeit: \(O(n)\), denn \(i \leq k + \ell \leq n\). |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Note 5: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Cloze
GUID: -+PkHTr|N.
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Datensatz und Duplikate
Ein Datensatz \(D = (s_1, s_2, \ldots, s_n)\) ist eine Folge von \(n\) Elementen.
Ein Paar \((i, j)\) mit \(1 \leq i < j \leq n\) heisst Duplikat in \(D\), falls \(s_i = s_j\).
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Datensatz und Duplikate
Ein Datensatz \(D = (s_1, s_2, \ldots, s_n)\) ist eine Folge von \(n\) Elementen.
Ein Paar \((i, j)\) mit \(1 \leq i < j \leq n\) heisst Duplikat in \(D\), falls \(s_i = s_j\).
Beispiel: \(D = (A, C, B, Z, C, B, C)\) mit Indizes \(1, \ldots, 7\). Dann ist \(\mathrm{Dupl}(D) = \{(2,5), (2,7), (5,7), (3,6)\}\), denn Position \(2, 5, 7\) tragen alle \(C\), und Position \(3, 6\) tragen \(B\).
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Datensatz und Duplikate</b><br>Ein <b>Datensatz</b> \(D = (s_1, s_2, \ldots, s_n)\) ist {{c1::eine Folge von \(n\) Elementen}}.<br>Ein Paar \((i, j)\) mit \(1 \leq i < j \leq n\) heisst <b>Duplikat</b> in \(D\), falls {{c2::\(s_i = s_j\)}}. |
| Extra |
|
Beispiel: \(D = (A, C, B, Z, C, B, C)\) mit Indizes \(1, \ldots, 7\). Dann ist \(\mathrm{Dupl}(D) = \{(2,5), (2,7), (5,7), (3,6)\}\), denn Position \(2, 5, 7\) tragen alle \(C\), und Position \(3, 6\) tragen \(B\). |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Note 6: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Classic
GUID: 5pn1{Da=cd
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Floyd's Cycle Finding (Phase 2)
Nach Phase 1 ist ein Treffpunkt mit \(i = k + r\) bekannt. Wie bestimmt man daraus die gesuchten Indizes \(i \neq j\) mit \(a[i] = a[j]\)?
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Floyd's Cycle Finding (Phase 2)
Nach Phase 1 ist ein Treffpunkt mit \(i = k + r\) bekannt. Wie bestimmt man daraus die gesuchten Indizes \(i \neq j\) mit \(a[i] = a[j]\)?
Beobachtung: Aus \(i = k + r\) folgt \(x_k = x_{i+k}\) (beide sind der
Eintrittsknoten des Kreises). Setze den Hasen auf \(n\) zurück und lasse beide mit
gleicher Geschwindigkeit laufen, dabei jeweils den Vorgänger merken:
hase := n
while (igel != hase):
i := igel
j := hase
igel := a[igel]
hase := a[hase]
return i, jWenn Hase und Igel sich wieder treffen, sind sie am Eintrittsknoten des Kreises. Die zwei Vorgänger \(i\) und \(j\) sind verschieden, zeigen aber per Konstruktion beide auf den Eintrittsknoten, das heisst \(a[i] = a[j]\).
Field-by-field Comparison
| Field |
Before |
After |
| Front |
|
<b>Floyd's Cycle Finding (Phase 2)</b><br>Nach Phase 1 ist ein Treffpunkt mit \(i = k + r\) bekannt. Wie bestimmt man daraus die gesuchten Indizes \(i \neq j\) mit \(a[i] = a[j]\)? |
| Back |
|
Beobachtung: Aus \(i = k + r\) folgt \(x_k = x_{i+k}\) (beide sind der <b>Eintrittsknoten</b> des Kreises). Setze den Hasen auf \(n\) zurück und lasse beide mit <b>gleicher</b> Geschwindigkeit laufen, dabei jeweils den Vorgänger merken:<br><pre>hase := n
while (igel != hase):
i := igel
j := hase
igel := a[igel]
hase := a[hase]
return i, j</pre>Wenn Hase und Igel sich wieder treffen, sind sie am Eintrittsknoten des Kreises. Die zwei Vorgänger \(i\) und \(j\) sind verschieden, zeigen aber per Konstruktion beide auf den Eintrittsknoten, das heisst \(a[i] = a[j]\). |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Note 7: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Classic
GUID: CMDdQgC0[y
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Lösung mit Hashmap
Beschreibe den Algorithmus und nenne den entscheidenden Unterschied zur Sortier-Lösung.
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Lösung mit Hashmap
Beschreibe den Algorithmus und nenne den entscheidenden Unterschied zur Sortier-Lösung.
Algorithmus:- Hashen und indexieren: \(((h(s_1), 1), (h(s_2), 2), \ldots, (h(s_n), n))\)
- Sortiere nach erster Koordinate (jetzt Hash-Werte aus \([m]\), nicht mehr die teuren Original-Elemente)
- Durchlaufe die sortierte Folge, um Duplikat-Kandidaten zu finden
- Wichtig: Kandidaten müssen noch auf mögliche Kollisionen geprüft werden, denn \(h(s_i) = h(s_j)\) impliziert nicht \(s_i = s_j\)
Vorteil: Sortieren erfolgt auf kleinen Hash-Werten, nicht auf den (teuren) Originalelementen.
Field-by-field Comparison
| Field |
Before |
After |
| Front |
|
<b>Lösung mit Hashmap</b><br>Beschreibe den Algorithmus und nenne den entscheidenden Unterschied zur Sortier-Lösung. |
| Back |
|
<b>Algorithmus:</b><ol><li>Hashen und indexieren: \(((h(s_1), 1), (h(s_2), 2), \ldots, (h(s_n), n))\)</li><li>Sortiere nach erster Koordinate (jetzt Hash-Werte aus \([m]\), nicht mehr die teuren Original-Elemente)</li><li>Durchlaufe die sortierte Folge, um Duplikat-Kandidaten zu finden</li><li><b>Wichtig:</b> Kandidaten müssen noch auf mögliche Kollisionen geprüft werden, denn \(h(s_i) = h(s_j)\) impliziert nicht \(s_i = s_j\)</li></ol><b>Vorteil:</b> Sortieren erfolgt auf kleinen Hash-Werten, nicht auf den (teuren) Originalelementen. |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Note 8: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Cloze
GUID: [u#wQ+Y.*n
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Floyd's Cycle Finding (Aufgabenstellung)Gegeben ein Array \(a[1, \ldots, n]\) mit \(a[i] \in \{1, \ldots, n-1\}\). Finde zwei Indizes \(i \neq j\) mit \(a[i] = a[j]\), unter folgenden Einschränkungen:
- Laufzeit \(O(n)\)
- Das Array \(a\) darf nicht verändert werden (Zugriffe \(a[i]\) sind beliebig oft erlaubt)
- Nur \(O(1)\) zusätzliche Speicherzellen
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Floyd's Cycle Finding (Aufgabenstellung)Gegeben ein Array \(a[1, \ldots, n]\) mit \(a[i] \in \{1, \ldots, n-1\}\). Finde zwei Indizes \(i \neq j\) mit \(a[i] = a[j]\), unter folgenden Einschränkungen:
- Laufzeit \(O(n)\)
- Das Array \(a\) darf nicht verändert werden (Zugriffe \(a[i]\) sind beliebig oft erlaubt)
- Nur \(O(1)\) zusätzliche Speicherzellen
Ein Duplikat existiert sicher, denn \(a\) hat \(n\) Einträge mit Werten aus einer Menge der Grösse \(n-1\) (Schubfachprinzip).
Diese Variante hat keine direkte praktische Bedeutung, zeigt aber, was mit guter algorithmischer Herangehensweise möglich ist.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Floyd's Cycle Finding (Aufgabenstellung)</b><br>Gegeben ein Array \(a[1, \ldots, n]\) mit \(a[i] \in \{1, \ldots, n-1\}\). Finde zwei Indizes \(i \neq j\) mit \(a[i] = a[j]\), unter folgenden Einschränkungen:<ul><li>Laufzeit {{c1::\(O(n)\)}}</li><li>{{c2::Das Array \(a\) darf nicht verändert werden}} (Zugriffe \(a[i]\) sind beliebig oft erlaubt)</li><li>Nur {{c3::\(O(1)\)}} zusätzliche Speicherzellen</li></ul> |
| Extra |
|
Ein Duplikat existiert sicher, denn \(a\) hat \(n\) Einträge mit Werten aus einer Menge der Grösse \(n-1\) (Schubfachprinzip).<br><br>Diese Variante hat keine direkte praktische Bedeutung, zeigt aber, was mit guter algorithmischer Herangehensweise möglich ist. |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Note 9: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Cloze
GUID: g0V)&ygKw?
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Kollision
Eine Kollision ist ein Paar \((i, j)\) mit \(1 \leq i < j \leq n\), \(s_i \neq s_j\) und \(h(s_i) = h(s_j)\).
Anschaulich: Kollisionen sind die neuen (unerwünschten) Duplikate in der Hashmap, also Hashmap-Duplikate, die im Original keine sind.
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Kollision
Eine Kollision ist ein Paar \((i, j)\) mit \(1 \leq i < j \leq n\), \(s_i \neq s_j\) und \(h(s_i) = h(s_j)\).
Anschaulich: Kollisionen sind die neuen (unerwünschten) Duplikate in der Hashmap, also Hashmap-Duplikate, die im Original keine sind.
Echte Duplikate (\(s_i = s_j\)) erzeugen automatisch übereinstimmende Hashes; das ist erwünscht. Kollisionen sind die zusätzlichen, unerwünschten Übereinstimmungen, die durch die Komprimierung \(|U| \to [m]\) entstehen.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Kollision</b><br>Eine <b>Kollision</b> ist {{c1::ein Paar \((i, j)\) mit \(1 \leq i < j \leq n\), \(s_i \neq s_j\) und \(h(s_i) = h(s_j)\)}}.<br>Anschaulich: Kollisionen sind {{c2::die neuen (unerwünschten) Duplikate in der Hashmap}}, also Hashmap-Duplikate, die im Original keine sind. |
| Extra |
|
Echte Duplikate (\(s_i = s_j\)) erzeugen automatisch übereinstimmende Hashes; das ist erwünscht. Kollisionen sind die zusätzlichen, unerwünschten Übereinstimmungen, die durch die Komprimierung \(|U| \to [m]\) entstehen. |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Note 10: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Cloze
GUID: hN,uV~s)@n
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Erwartete Anzahl Kollisionen
Für eine Hashfunktion \(h : U \to [m]\) mit \(\Pr[h(u) = i] = \tfrac{1}{m}\) gilt:\[\mathbb{E}[\#\text{Kollisionen}] \leq {{c1::\binom{n}{2} \cdot \tfrac{1}{m}}}.\]Insbesondere folgt mit der Wahl \(m = n^2\): \(\mathbb{E}[\#\text{Kollisionen}] < 1\).
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Erwartete Anzahl Kollisionen
Für eine Hashfunktion \(h : U \to [m]\) mit \(\Pr[h(u) = i] = \tfrac{1}{m}\) gilt:\[\mathbb{E}[\#\text{Kollisionen}] \leq {{c1::\binom{n}{2} \cdot \tfrac{1}{m}}}.\]Insbesondere folgt mit der Wahl \(m = n^2\): \(\mathbb{E}[\#\text{Kollisionen}] < 1\).
Beweisidee: Für jedes feste Paar \((i, j)\) mit \(s_i \neq s_j\) gilt \(\Pr[h(s_i) = h(s_j)] = \tfrac{1}{m}\) (wegen Unabhängigkeit / Zufallsfunktion). Es gibt höchstens \(\binom{n}{2}\) solche Paare, und Linearität des Erwartungswerts liefert die Schranke.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Erwartete Anzahl Kollisionen</b><br>Für eine Hashfunktion \(h : U \to [m]\) mit \(\Pr[h(u) = i] = \tfrac{1}{m}\) gilt:\[\mathbb{E}[\#\text{Kollisionen}] \leq {{c1::\binom{n}{2} \cdot \tfrac{1}{m}}}.\]Insbesondere folgt mit der Wahl \(m = n^2\): \(\mathbb{E}[\#\text{Kollisionen}] {{c2::< 1}}\). |
| Extra |
|
Beweisidee: Für jedes feste Paar \((i, j)\) mit \(s_i \neq s_j\) gilt \(\Pr[h(s_i) = h(s_j)] = \tfrac{1}{m}\) (wegen Unabhängigkeit / Zufallsfunktion). Es gibt höchstens \(\binom{n}{2}\) solche Paare, und Linearität des Erwartungswerts liefert die Schranke. |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Note 11: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Cloze
GUID: unEExu6hiJ
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Floyd's Cycle Finding (Resultat)Auf einem Array \(a[1, \ldots, n]\) mit \(a[i] \in \{1, \ldots, n-1\}\) findet der Hase-und-Igel-Algorithmus zwei Indizes \(i \neq j\) mit \(a[i] = a[j]\) in:
- Laufzeit \(O(n)\)
- Zusätzlicher Speicher: nur vier Variablen (igel, hase, i, j)
Das Array \(a\) wird dabei
nicht verändert.
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Floyd's Cycle Finding (Resultat)Auf einem Array \(a[1, \ldots, n]\) mit \(a[i] \in \{1, \ldots, n-1\}\) findet der Hase-und-Igel-Algorithmus zwei Indizes \(i \neq j\) mit \(a[i] = a[j]\) in:
- Laufzeit \(O(n)\)
- Zusätzlicher Speicher: nur vier Variablen (igel, hase, i, j)
Das Array \(a\) wird dabei
nicht verändert.
Bemerkenswert: Die offensichtliche Hashmap-Lösung benötigt \(\Theta(n \log n)\) Zusatzspeicher; Floyd's Algorithmus kommt mit \(O(1)\) Zusatzspeicher aus, ohne die Laufzeitschranke zu opfern.
Der Algorithmus ist deterministisch und (anders als Hashmap/Bloomfilter) nicht randomisiert: er steht hier als Kontrast und Highlight, nicht als randomisierter Algorithmus.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Floyd's Cycle Finding (Resultat)</b><br>Auf einem Array \(a[1, \ldots, n]\) mit \(a[i] \in \{1, \ldots, n-1\}\) findet der Hase-und-Igel-Algorithmus zwei Indizes \(i \neq j\) mit \(a[i] = a[j]\) in:<ul><li>Laufzeit {{c1::\(O(n)\)}}</li><li>Zusätzlicher Speicher: {{c2::nur vier Variablen}} (igel, hase, i, j)</li></ul>Das Array \(a\) wird dabei {{c3::nicht verändert}}. |
| Extra |
|
Bemerkenswert: Die offensichtliche Hashmap-Lösung benötigt \(\Theta(n \log n)\) Zusatzspeicher; Floyd's Algorithmus kommt mit \(O(1)\) Zusatzspeicher aus, ohne die Laufzeitschranke zu opfern.<br><br>Der Algorithmus ist deterministisch und (anders als Hashmap/Bloomfilter) <b>nicht</b> randomisiert: er steht hier als Kontrast und Highlight, nicht als randomisierter Algorithmus. |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Note 12: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Classic
GUID: vJ-_bexxr5
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Erste Lösung für das Duplikate-finden-Problem
Beschreibe den Algorithmus und gib seine Laufzeit an.
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Erste Lösung für das Duplikate-finden-Problem
Beschreibe den Algorithmus und gib seine Laufzeit an.
Algorithmus:- Indexiere: \(((s_1, 1), (s_2, 2), \ldots, (s_n, n))\).
- Sortiere die Folge nach der ersten Koordinate.
- Durchlaufe die sortierte Folge, um Duplikate zu finden (gleiche Werte stehen jetzt benachbart).
Analyse:- Sortieren: \(O(n \log n)\) Vergleiche und Speicherzugriffe
- Durchlaufen: \(O(n + |\mathrm{Dupl}(D)|)\)
Field-by-field Comparison
| Field |
Before |
After |
| Front |
|
<b>Erste Lösung für das Duplikate-finden-Problem</b><br>Beschreibe den Algorithmus und gib seine Laufzeit an. |
| Back |
|
<b>Algorithmus:</b><ol><li>Indexiere: \(((s_1, 1), (s_2, 2), \ldots, (s_n, n))\).</li><li>Sortiere die Folge nach der ersten Koordinate.</li><li>Durchlaufe die sortierte Folge, um Duplikate zu finden (gleiche Werte stehen jetzt benachbart).</li></ol><b>Analyse:</b><ul><li>Sortieren: \(O(n \log n)\) Vergleiche und Speicherzugriffe</li><li>Durchlaufen: \(O(n + |\mathrm{Dupl}(D)|)\)</li></ul> |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Note 13: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Cloze
GUID: {(x$*~gqX=
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Wichtige Eigenschaften der Hashwerte
Jedes \(h(s_i)\) ist zufällig gleichverteilt in \([m]\), aber es gilt deterministisch \(s_i = s_j \Rightarrow h(s_i) = h(s_j)\).
Wir wählen \(m\) viel kleiner als \(|U|\), also Komprimierung.
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Wichtige Eigenschaften der Hashwerte
Jedes \(h(s_i)\) ist zufällig gleichverteilt in \([m]\), aber es gilt deterministisch \(s_i = s_j \Rightarrow h(s_i) = h(s_j)\).
Wir wählen \(m\) viel kleiner als \(|U|\), also Komprimierung.
Die Implikation \(s_i = s_j \Rightarrow h(s_i) = h(s_j)\) ist nötig, damit echte Duplikate auch im Hash-Raum als Duplikate erscheinen. Die Umkehrung gilt im Allgemeinen nicht: zwei verschiedene Elemente können denselben Hash-Wert haben (Kollision).
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Wichtige Eigenschaften der Hashwerte</b><br>Jedes \(h(s_i)\) ist {{c1::zufällig gleichverteilt in \([m]\)}}, aber es gilt deterministisch {{c2::\(s_i = s_j \Rightarrow h(s_i) = h(s_j)\)}}.<br>Wir wählen \(m\) viel kleiner als \(|U|\), also {{c3::Komprimierung}}. |
| Extra |
|
Die Implikation \(s_i = s_j \Rightarrow h(s_i) = h(s_j)\) ist nötig, damit echte Duplikate auch im Hash-Raum als Duplikate erscheinen. Die Umkehrung gilt im Allgemeinen <b>nicht</b>: zwei verschiedene Elemente können denselben Hash-Wert haben (Kollision). |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::6._Duplikate_finden
Note 14: ETH::2. Semester::A&W
Deck: ETH::2. Semester::A&W
Note Type: Horvath Cloze
GUID: |(%V*=bZ6e
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Floyd's Cycle Finding (Graph-Reformulierung)Definiere den gerichteten Graphen \(D = (V, A)\) mit
\(V = [n]\) und {{c2::\(A = \{(i, a[i]) \mid 1 \leq i \leq n\}\)}}.
Eigenschaften:
- Jeder Knoten hat genau eine ausgehende Kante
- Knoten \(n\) hat keine eingehende Kante (weil \(a[i] \neq n\) für alle \(i\))
- Der von Knoten \(n\) ausgehende Subgraph (immer der ausgehenden Kante folgen) besteht aus einem Pfad gefolgt von einem Kreis (\(\rho\)-Form)
Back
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Floyd's Cycle Finding (Graph-Reformulierung)Definiere den gerichteten Graphen \(D = (V, A)\) mit
\(V = [n]\) und {{c2::\(A = \{(i, a[i]) \mid 1 \leq i \leq n\}\)}}.
Eigenschaften:
- Jeder Knoten hat genau eine ausgehende Kante
- Knoten \(n\) hat keine eingehende Kante (weil \(a[i] \neq n\) für alle \(i\))
- Der von Knoten \(n\) ausgehende Subgraph (immer der ausgehenden Kante folgen) besteht aus einem Pfad gefolgt von einem Kreis (\(\rho\)-Form)
Notation: Pfad hat \(k \geq 1\) Kanten, Kreis hat \(\ell \geq 3\) Kanten, mit \(k + \ell \leq n\).
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Floyd's Cycle Finding (Graph-Reformulierung)</b><br>Definiere den gerichteten Graphen \(D = (V, A)\) mit {{c1::\(V = [n]\)}} und {{c2::\(A = \{(i, a[i]) \mid 1 \leq i \leq n\}\)}}.<br>Eigenschaften:<ul><li>Jeder Knoten hat genau {{c3::eine ausgehende Kante}}</li><li>Knoten \(n\) hat {{c4::keine eingehende Kante}} (weil \(a[i] \neq n\) für alle \(i\))</li><li>Der von Knoten \(n\) ausgehende Subgraph (immer der ausgehenden Kante folgen) besteht aus {{c5::einem Pfad gefolgt von einem Kreis}} (\(\rho\)-Form)</li></ul> |
| Extra |
|
Notation: Pfad hat \(k \geq 1\) Kanten, Kreis hat \(\ell \geq 3\) Kanten, mit \(k + \ell \leq n\). |
Tags:
ETH::2._Semester::A&W::2._Wahrscheinlichkeitstheorie_und_randomisierte_Algorithmen::8._Randomisierte_Algorithmen::7._Floyds_Cycle_Finding
Note 15: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: $}DD/7f+@3
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Bei der bimolekularen Reaktion \(A + B \to C\) ist die DGl \(u'(t) = k(a - u)(b - u)\) und nicht \(u'(t) = k(a + u)(b + u)\), weil:
Die Ausgangsstoffe \(A\) und \(B\) liegen in endlicher Menge vor und werden mit der Reaktion verbraucht. Die verbleibenden Mengen sind \(a - u\) bzw. \(b - u\), nicht \(a + u\) bzw. \(b + u\).
Konsequenz: Die Reaktion stoppt, sobald \(u = \min(a, b)\), weil dann ein Edukt aufgebraucht ist und \(u' = 0\) wird.
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Bei der bimolekularen Reaktion \(A + B \to C\) ist die DGl \(u'(t) = k(a - u)(b - u)\) und nicht \(u'(t) = k(a + u)(b + u)\), weil:
Die Ausgangsstoffe \(A\) und \(B\) liegen in endlicher Menge vor und werden mit der Reaktion verbraucht. Die verbleibenden Mengen sind \(a - u\) bzw. \(b - u\), nicht \(a + u\) bzw. \(b + u\).
Konsequenz: Die Reaktion stoppt, sobald \(u = \min(a, b)\), weil dann ein Edukt aufgebraucht ist und \(u' = 0\) wird.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Bei der bimolekularen Reaktion \(A + B \to C\) ist die DGl \(u'(t) = k(a - u)(b - u)\) und <b>nicht</b> \(u'(t) = k(a + u)(b + u)\), weil:<br><br>{{c1::Die Ausgangsstoffe \(A\) und \(B\) liegen in <b>endlicher Menge</b> vor und werden mit der Reaktion <b>verbraucht</b>. Die verbleibenden Mengen sind \(a - u\) bzw. \(b - u\), nicht \(a + u\) bzw. \(b + u\).}}<br><br>Konsequenz: {{c2::Die Reaktion <b>stoppt</b>, sobald \(u = \min(a, b)\), weil dann ein Edukt aufgebraucht ist und \(u' = 0\) wird.}} |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Note 16: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: &w#tm2.1,Y
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::1._Klassifizierung
Eine lineare Differentialgleichung \(a_n(x) y^{(n)} + \dots + a_0(x) y = s(x)\) heisst DGl mit konstanten Koeffizienten, falls alle Funktionen \(a_i(x)\) konstante Funktionen sind (d.h. \(a_i(x) = a_i \in \mathbb{R}\)).
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::1._Klassifizierung
Eine lineare Differentialgleichung \(a_n(x) y^{(n)} + \dots + a_0(x) y = s(x)\) heisst DGl mit konstanten Koeffizienten, falls alle Funktionen \(a_i(x)\) konstante Funktionen sind (d.h. \(a_i(x) = a_i \in \mathbb{R}\)).
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Eine lineare Differentialgleichung \(a_n(x) y^{(n)} + \dots + a_0(x) y = s(x)\) heisst <b>DGl mit konstanten Koeffizienten</b>, falls {{c1::alle Funktionen \(a_i(x)\) konstante Funktionen sind}} (d.h. \(a_i(x) = a_i \in \mathbb{R}\)). |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::1._Klassifizierung
Note 17: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: )hn#lezg{!
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::2._Lösungsstruktur
Satz (Fundamentallösungen): Eine lineare, homogene Differentialgleichung der Ordnung \(n\) besitzt \(n\) Lösungen \(y_1(x), \dots, y_n(x)\), sodass die allgemeine Lösung gegeben ist durch
\[ y(x) = C_1 y_1(x) + \dots + C_n y_n(x), \quad C_1, \dots, C_n \in \mathbb{R} \]Diese Lösungen werden Fundamentallösungen genannt.
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::2._Lösungsstruktur
Satz (Fundamentallösungen): Eine lineare, homogene Differentialgleichung der Ordnung \(n\) besitzt \(n\) Lösungen \(y_1(x), \dots, y_n(x)\), sodass die allgemeine Lösung gegeben ist durch
\[ y(x) = C_1 y_1(x) + \dots + C_n y_n(x), \quad C_1, \dots, C_n \in \mathbb{R} \]Diese Lösungen werden Fundamentallösungen genannt.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Satz (Fundamentallösungen):</b> Eine lineare, homogene Differentialgleichung der Ordnung \(n\) besitzt {{c1::\(n\) Lösungen \(y_1(x), \dots, y_n(x)\)}}, sodass die <b>allgemeine Lösung</b> gegeben ist durch<br>\[ {{c2::y(x) = C_1 y_1(x) + \dots + C_n y_n(x), \quad C_1, \dots, C_n \in \mathbb{R}}} \]Diese Lösungen werden {{c3::<b>Fundamentallösungen</b>}} genannt. |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::2._Lösungsstruktur
Note 18: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: 64..u6&9G{
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Beschränktes (logistisches) Wachstum mit Wachstumskonstante \(k > 0\) und Kapazitätsgrenze \(L > 0\):
\[ {{c1::u'(t) = k\,u(t)\left(1 - \dfrac{u(t)}{L}\right)}} \]
Charakteristisches Verhalten:
- Für \(u(t) \ll L\): nahezu exponentielles Wachstum \(u' \approx k\,u\)
- Für \(u(t) \to L\): Wachstumsrate \(u' \to 0\), die Grösse stagniert bei der Kapazität \(L\)
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Beschränktes (logistisches) Wachstum mit Wachstumskonstante \(k > 0\) und Kapazitätsgrenze \(L > 0\):
\[ {{c1::u'(t) = k\,u(t)\left(1 - \dfrac{u(t)}{L}\right)}} \]
Charakteristisches Verhalten:
- Für \(u(t) \ll L\): nahezu exponentielles Wachstum \(u' \approx k\,u\)
- Für \(u(t) \to L\): Wachstumsrate \(u' \to 0\), die Grösse stagniert bei der Kapazität \(L\)
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Beschränktes (logistisches) Wachstum</b> mit Wachstumskonstante \(k > 0\) und Kapazitätsgrenze \(L > 0\):<br><br>\[ {{c1::u'(t) = k\,u(t)\left(1 - \dfrac{u(t)}{L}\right)}} \]<br>Charakteristisches Verhalten:<ul><li>Für \(u(t) \ll L\): {{c2::nahezu exponentielles Wachstum \(u' \approx k\,u\)}}</li><li>Für \(u(t) \to L\): {{c3::Wachstumsrate \(u' \to 0\), die Grösse stagniert bei der Kapazität \(L\)}}</li></ul> |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Note 19: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: =x+CE-oxI#
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::3._Eulerscher_Ansatz
Zum Lösen einer linearen, homogenen DGl mit konstanten Koeffizienten
\[ a_n u^{(n)}(x) + a_{n-1} u^{(n-1)}(x) + \dots + a_1 u'(x) + a_0 u(x) = 0 \]verwendet man den Eulerschen Ansatz:
\[ u(x) = e^{\lambda x} \]Einsetzen liefert die charakteristische Gleichung
\[ {{c2::a_n \lambda^n + a_{n-1} \lambda^{n-1} + \dots + a_1 \lambda + a_0 = 0}} \]bzw. das charakteristische Polynom {{c3::\(p(\lambda) = a_n \lambda^n + a_{n-1} \lambda^{n-1} + \dots + a_1 \lambda + a_0\)}}.
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::3._Eulerscher_Ansatz
Zum Lösen einer linearen, homogenen DGl mit konstanten Koeffizienten
\[ a_n u^{(n)}(x) + a_{n-1} u^{(n-1)}(x) + \dots + a_1 u'(x) + a_0 u(x) = 0 \]verwendet man den Eulerschen Ansatz:
\[ u(x) = e^{\lambda x} \]Einsetzen liefert die charakteristische Gleichung
\[ {{c2::a_n \lambda^n + a_{n-1} \lambda^{n-1} + \dots + a_1 \lambda + a_0 = 0}} \]bzw. das charakteristische Polynom {{c3::\(p(\lambda) = a_n \lambda^n + a_{n-1} \lambda^{n-1} + \dots + a_1 \lambda + a_0\)}}.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Zum Lösen einer linearen, homogenen DGl mit konstanten Koeffizienten<br>\[ a_n u^{(n)}(x) + a_{n-1} u^{(n-1)}(x) + \dots + a_1 u'(x) + a_0 u(x) = 0 \]verwendet man den <b>Eulerschen Ansatz</b>:<br>\[ {{c1::u(x) = e^{\lambda x}}} \]Einsetzen liefert die <b>charakteristische Gleichung</b><br>\[ {{c2::a_n \lambda^n + a_{n-1} \lambda^{n-1} + \dots + a_1 \lambda + a_0 = 0}} \]bzw. das <b>charakteristische Polynom</b> {{c3::\(p(\lambda) = a_n \lambda^n + a_{n-1} \lambda^{n-1} + \dots + a_1 \lambda + a_0\)}}. |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::3._Eulerscher_Ansatz
Note 20: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: Ij@&w9=oPW
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::3._Eulerscher_Ansatz
Allgemeine Lösung (nur reelle Nullstellen): Hat das charakteristische Polynom einer linearen, homogenen DGl mit konstanten Koeffizienten ausschliesslich reelle Nullstellen \(\lambda_i\) mit Multiplizität \(m_i\) (\(i = 1, \dots, r\)), so ist die allgemeine Lösung
\[ {{c1::u(x) = \sum_{i=1}^{r} \left( \sum_{p=0}^{m_i - 1} C_{ip}\, x^p \right) e^{\lambda_i x}}} \]Pro Nullstelle \(\lambda_i\) liefert das also {{c2::\(m_i\) Fundamentallösungen \(e^{\lambda_i x}, x e^{\lambda_i x}, \dots, x^{m_i - 1} e^{\lambda_i x}\)}}.
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::3._Eulerscher_Ansatz
Allgemeine Lösung (nur reelle Nullstellen): Hat das charakteristische Polynom einer linearen, homogenen DGl mit konstanten Koeffizienten ausschliesslich reelle Nullstellen \(\lambda_i\) mit Multiplizität \(m_i\) (\(i = 1, \dots, r\)), so ist die allgemeine Lösung
\[ {{c1::u(x) = \sum_{i=1}^{r} \left( \sum_{p=0}^{m_i - 1} C_{ip}\, x^p \right) e^{\lambda_i x}}} \]Pro Nullstelle \(\lambda_i\) liefert das also {{c2::\(m_i\) Fundamentallösungen \(e^{\lambda_i x}, x e^{\lambda_i x}, \dots, x^{m_i - 1} e^{\lambda_i x}\)}}.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Allgemeine Lösung (nur reelle Nullstellen):</b> Hat das charakteristische Polynom einer linearen, homogenen DGl mit konstanten Koeffizienten ausschliesslich reelle Nullstellen \(\lambda_i\) mit Multiplizität \(m_i\) (\(i = 1, \dots, r\)), so ist die allgemeine Lösung<br>\[ {{c1::u(x) = \sum_{i=1}^{r} \left( \sum_{p=0}^{m_i - 1} C_{ip}\, x^p \right) e^{\lambda_i x}}} \]Pro Nullstelle \(\lambda_i\) liefert das also {{c2::\(m_i\) Fundamentallösungen \(e^{\lambda_i x}, x e^{\lambda_i x}, \dots, x^{m_i - 1} e^{\lambda_i x}\)}}. |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::3._Eulerscher_Ansatz
Note 21: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: PYb5.02vXc
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::1._Klassifizierung
Eine Differentialgleichung der Form
\[ a_n(x) y^{(n)}(x) + a_{n-1}(x) y^{(n-1)}(x) + \dots + a_1(x) y'(x) + a_0(x) y(x) = s(x) \]heisst
lineare Differentialgleichung mit Koeffizienten \(a_i(x)\).
- Die Ordnung der DGl ist die maximale Ordnung der vorkommenden Ableitungen.
- Die Funktion \(s(x)\) nennt man Störfunktion.
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::1._Klassifizierung
Eine Differentialgleichung der Form
\[ a_n(x) y^{(n)}(x) + a_{n-1}(x) y^{(n-1)}(x) + \dots + a_1(x) y'(x) + a_0(x) y(x) = s(x) \]heisst
lineare Differentialgleichung mit Koeffizienten \(a_i(x)\).
- Die Ordnung der DGl ist die maximale Ordnung der vorkommenden Ableitungen.
- Die Funktion \(s(x)\) nennt man Störfunktion.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Eine Differentialgleichung der Form<br>\[ a_n(x) y^{(n)}(x) + a_{n-1}(x) y^{(n-1)}(x) + \dots + a_1(x) y'(x) + a_0(x) y(x) = s(x) \]heisst {{c1::<b>lineare Differentialgleichung</b>}} mit Koeffizienten \(a_i(x)\).<br><br><ul><li>Die <b>Ordnung</b> der DGl ist {{c2::die maximale Ordnung der vorkommenden Ableitungen}}.</li><li>Die Funktion \(s(x)\) nennt man {{c3::<b>Störfunktion</b>}}.</li></ul> |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::1._Klassifizierung
Note 22: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: Qp3^E,]TbW
modified
Before
Front
ETH::2._Semester::Analysis::4._Funktionen::4._Elementare_Funktionen::6._Transformationen
Alle drei Transformationen (Streckung/Verschiebung in x- und y-Richtung) sind darstellbar als zusammengesetzte Funktion: \[ g(x) = s(u(x)) = s \circ u(x) \]Dabei nennt man \(s\) die äussere und \(u\) die innere Funktion.
Back
ETH::2._Semester::Analysis::4._Funktionen::4._Elementare_Funktionen::6._Transformationen
Alle drei Transformationen (Streckung/Verschiebung in x- und y-Richtung) sind darstellbar als zusammengesetzte Funktion: \[ g(x) = s(u(x)) = s \circ u(x) \]Dabei nennt man \(s\) die äussere und \(u\) die innere Funktion.
Beispiel: Die horizontale Verschiebung \(g(x) = f(x + k)\) lässt sich schreiben als \(g(x) = f(h(x))\) mit innerer Funktion \(h(x) = x + k\).
After
Front
ETH::2._Semester::Analysis::4._Funktionen::4._Elementare_Funktionen::6._Transformationen
Alle drei Transformationen (Streckung/Verschiebung in x- und y-Richtung) sind darstellbar als zusammengesetzte Funktion: \[ g(x) = s(u(x)) = s \circ u(x) \]Dabei nennt man \(s\) die äussere und \(u\) die innere Funktion.
Back
ETH::2._Semester::Analysis::4._Funktionen::4._Elementare_Funktionen::6._Transformationen
Alle drei Transformationen (Streckung/Verschiebung in x- und y-Richtung) sind darstellbar als zusammengesetzte Funktion: \[ g(x) = s(u(x)) = s \circ u(x) \]Dabei nennt man \(s\) die äussere und \(u\) die innere Funktion.
Beispiel: Die horizontale Verschiebung \(g(x) = f(x + k)\) lässt sich schreiben als \(g(x) = f(h(x))\) mit innerer Funktion \(h(x) = x + k\).
Field-by-field Comparison
| Field |
Before |
After |
| Text |
Alle drei Transformationen (Streckung/Verschiebung in x- und y-Richtung) sind darstellbar als <i>zusammengesetzte Funktion</i>: \[ g(x) = s(u(x)) = s \circ u(x) \]Dabei nennt man \(s\) die {{c1::äussere}} und \(u\) die {{c2::innere}} Funktion. |
Alle drei Transformationen (Streckung/Verschiebung in x- und y-Richtung) sind darstellbar als <i>zusammengesetzte Funktion</i>: \[ g(x) = s(u(x)) = s \circ u(x) \]Dabei nennt man \(s\) die {{c1::äussere}} und \(u\) die {{c1::innere}} Funktion. |
Tags:
ETH::2._Semester::Analysis::4._Funktionen::4._Elementare_Funktionen::6._Transformationen
Note 23: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: W!ocL61JGV
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::1._Klassifizierung
Eine lineare Differentialgleichung
\[ a_n(x) y^{(n)}(x) + \dots + a_0(x) y(x) = s(x) \]heisst:
- homogen, falls \(s(x) = 0\)
- inhomogen, falls \(s(x) \neq 0\)
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::1._Klassifizierung
Eine lineare Differentialgleichung
\[ a_n(x) y^{(n)}(x) + \dots + a_0(x) y(x) = s(x) \]heisst:
- homogen, falls \(s(x) = 0\)
- inhomogen, falls \(s(x) \neq 0\)
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Eine lineare Differentialgleichung<br>\[ a_n(x) y^{(n)}(x) + \dots + a_0(x) y(x) = s(x) \]heisst:<ul><li>{{c1::<b>homogen</b>}}, falls {{c2::\(s(x) = 0\)}}</li><li>{{c1::<b>inhomogen</b>}}, falls {{c2::\(s(x) \neq 0\)}}</li></ul> |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::1._Klassifizierung
Note 24: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: X.y:I?=bL;
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::3._Eulerscher_Ansatz
Allgemeine Lösung (mit komplexen Nullstellen): Hat das charakteristische Polynom \(r\) reelle Nullstellen \(\lambda_i\) (Multiplizität \(m_i\)) und \(s\) Paare komplexer Nullstellen \(a_j \pm i b_j\) (Multiplizität \(m_j\)), so ist die allgemeine Lösung
\[ \begin{gathered} u(x) = \sum_{i=1}^{r} \left( \sum_{p=0}^{m_i - 1} C_{ip}\, x^p \right) e^{\lambda_i x} \\ {{c1::+ \sum_{j=1}^{s} \sum_{q=0}^{m_j - 1} \left( A_{jq}\, x^q\, e^{a_j x} \sin(b_j x) + B_{jq}\, x^q\, e^{a_j x} \cos(b_j x) \right)}} \end{gathered} \]
Pro komplexem Paar \(a_j \pm i b_j\) treten also Fundamentallösungen der Form {{c2::\(x^q e^{a_j x} \sin(b_j x)\) und \(x^q e^{a_j x} \cos(b_j x)\) für \(q = 0, \dots, m_j - 1\)}} auf.
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::3._Eulerscher_Ansatz
Allgemeine Lösung (mit komplexen Nullstellen): Hat das charakteristische Polynom \(r\) reelle Nullstellen \(\lambda_i\) (Multiplizität \(m_i\)) und \(s\) Paare komplexer Nullstellen \(a_j \pm i b_j\) (Multiplizität \(m_j\)), so ist die allgemeine Lösung
\[ \begin{gathered} u(x) = \sum_{i=1}^{r} \left( \sum_{p=0}^{m_i - 1} C_{ip}\, x^p \right) e^{\lambda_i x} \\ {{c1::+ \sum_{j=1}^{s} \sum_{q=0}^{m_j - 1} \left( A_{jq}\, x^q\, e^{a_j x} \sin(b_j x) + B_{jq}\, x^q\, e^{a_j x} \cos(b_j x) \right)}} \end{gathered} \]
Pro komplexem Paar \(a_j \pm i b_j\) treten also Fundamentallösungen der Form {{c2::\(x^q e^{a_j x} \sin(b_j x)\) und \(x^q e^{a_j x} \cos(b_j x)\) für \(q = 0, \dots, m_j - 1\)}} auf.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Allgemeine Lösung (mit komplexen Nullstellen):</b> Hat das charakteristische Polynom \(r\) reelle Nullstellen \(\lambda_i\) (Multiplizität \(m_i\)) und \(s\) Paare komplexer Nullstellen \(a_j \pm i b_j\) (Multiplizität \(m_j\)), so ist die allgemeine Lösung<br>\[ \begin{gathered} u(x) = \sum_{i=1}^{r} \left( \sum_{p=0}^{m_i - 1} C_{ip}\, x^p \right) e^{\lambda_i x} \\ {{c1::+ \sum_{j=1}^{s} \sum_{q=0}^{m_j - 1} \left( A_{jq}\, x^q\, e^{a_j x} \sin(b_j x) + B_{jq}\, x^q\, e^{a_j x} \cos(b_j x) \right)}} \end{gathered} \]<br>Pro komplexem Paar \(a_j \pm i b_j\) treten also Fundamentallösungen der Form {{c2::\(x^q e^{a_j x} \sin(b_j x)\) und \(x^q e^{a_j x} \cos(b_j x)\) für \(q = 0, \dots, m_j - 1\)}} auf. |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::3._Eulerscher_Ansatz
Note 25: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: XD?:-{*nv*
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::4._Bedingungen
Die allgemeine Lösung einer DGl der Ordnung \(n\) enthält \(n\) freie Konstanten. Um eine konkrete Lösung auszuwählen, muss man also \(n\) Bedingungen vorgeben. Zwei Strategien:
Anfangswertproblem (AWP): Alle Bedingungen werden an derselben Stelle \(t_0\) vorgegeben, z.B. für \(n = 2\): \(u(t_0) = u_0,\ u'(t_0) = v_0\).
Randwertproblem (RWP): Die Bedingungen werden an verschiedenen Stellen vorgegeben, z.B. für \(n = 2\): \(u(t_0) = u_0,\ u(t_1) = u_1\) mit \(t_0 \neq t_1\).
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::4._Bedingungen
Die allgemeine Lösung einer DGl der Ordnung \(n\) enthält \(n\) freie Konstanten. Um eine konkrete Lösung auszuwählen, muss man also \(n\) Bedingungen vorgeben. Zwei Strategien:
Anfangswertproblem (AWP): Alle Bedingungen werden an derselben Stelle \(t_0\) vorgegeben, z.B. für \(n = 2\): \(u(t_0) = u_0,\ u'(t_0) = v_0\).
Randwertproblem (RWP): Die Bedingungen werden an verschiedenen Stellen vorgegeben, z.B. für \(n = 2\): \(u(t_0) = u_0,\ u(t_1) = u_1\) mit \(t_0 \neq t_1\).
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Die allgemeine Lösung einer DGl der Ordnung \(n\) enthält {{c1::\(n\) freie Konstanten}}. Um eine konkrete Lösung auszuwählen, muss man also \(n\) Bedingungen vorgeben. Zwei Strategien:<br><br><b>Anfangswertproblem (AWP):</b> {{c2::Alle Bedingungen werden an <b>derselben Stelle</b> \(t_0\) vorgegeben}}, z.B. für \(n = 2\): {{c3::\(u(t_0) = u_0,\ u'(t_0) = v_0\)}}.<br><br><b>Randwertproblem (RWP):</b> {{c4::Die Bedingungen werden an <b>verschiedenen Stellen</b> vorgegeben}}, z.B. für \(n = 2\): {{c5::\(u(t_0) = u_0,\ u(t_1) = u_1\) mit \(t_0 \neq t_1\)}}. |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::4._Bedingungen
Note 26: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: [qecP[HHF2
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Welche der folgenden DGl beschreibt
beschränktes Wachstum (eine Grösse, die nicht beliebig gross werden kann)?
- \(u' = k\,u \cdot \dfrac{u}{L}\): nicht beschränkt: für \(u \to \infty\) wächst \(u'\) sogar quadratisch
- \(u' = k\,u\,\bigl(1 + \dfrac{u}{L}\bigr)\): nicht beschränkt: \(u'\) wächst mit \(u\) immer schneller
- \(u' = k\,u\,\dfrac{L}{u} = k\,L\): nicht beschränkt: konstantes Wachstum, also lineares unbegrenztes Wachstum
- \(u' = k\,u\,\bigl(1 - \dfrac{u}{L}\bigr)\): beschränkt, da \(u' \to 0\) für \(u \to L\)
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Welche der folgenden DGl beschreibt
beschränktes Wachstum (eine Grösse, die nicht beliebig gross werden kann)?
- \(u' = k\,u \cdot \dfrac{u}{L}\): nicht beschränkt: für \(u \to \infty\) wächst \(u'\) sogar quadratisch
- \(u' = k\,u\,\bigl(1 + \dfrac{u}{L}\bigr)\): nicht beschränkt: \(u'\) wächst mit \(u\) immer schneller
- \(u' = k\,u\,\dfrac{L}{u} = k\,L\): nicht beschränkt: konstantes Wachstum, also lineares unbegrenztes Wachstum
- \(u' = k\,u\,\bigl(1 - \dfrac{u}{L}\bigr)\): beschränkt, da \(u' \to 0\) für \(u \to L\)
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Welche der folgenden DGl beschreibt <b>beschränktes Wachstum</b> (eine Grösse, die nicht beliebig gross werden kann)?<ul><li>\(u' = k\,u \cdot \dfrac{u}{L}\): {{c1::nicht beschränkt: für \(u \to \infty\) wächst \(u'\) sogar quadratisch}}</li><li>\(u' = k\,u\,\bigl(1 + \dfrac{u}{L}\bigr)\): {{c1::nicht beschränkt: \(u'\) wächst mit \(u\) immer schneller}}</li><li>\(u' = k\,u\,\dfrac{L}{u} = k\,L\): {{c1::nicht beschränkt: konstantes Wachstum, also lineares unbegrenztes Wachstum}}</li><li>\(u' = k\,u\,\bigl(1 - \dfrac{u}{L}\bigr)\): {{c2::beschränkt, da \(u' \to 0\) für \(u \to L\)}}</li></ul> |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Note 27: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: ]e,H2sK$mq
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::3._Mechanik
Mechanische Probleme: Bewegung wird über die wirkenden Kräfte modelliert. Nach Newton gilt für jede Kraft \(F\):
\[ {{c1::F = m\,\ddot{y} = m\,a}} \]
wobei \(y\) die Position des Körpers und {{c3::\(a = \ddot{y}\) seine Beschleunigung}} ist. Die DGl entsteht, indem alle Kräfte aufsummiert und gleich \(m\,\ddot{y}\) gesetzt werden.
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::3._Mechanik
Mechanische Probleme: Bewegung wird über die wirkenden Kräfte modelliert. Nach Newton gilt für jede Kraft \(F\):
\[ {{c1::F = m\,\ddot{y} = m\,a}} \]
wobei \(y\) die Position des Körpers und {{c3::\(a = \ddot{y}\) seine Beschleunigung}} ist. Die DGl entsteht, indem alle Kräfte aufsummiert und gleich \(m\,\ddot{y}\) gesetzt werden.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Mechanische Probleme:</b> Bewegung wird über die wirkenden Kräfte modelliert. Nach Newton gilt für jede Kraft \(F\):<br><br>\[ {{c1::F = m\,\ddot{y} = m\,a}} \]<br>wobei {{c2::\(y\) die Position des Körpers}} und {{c3::\(a = \ddot{y}\) seine Beschleunigung}} ist. Die DGl entsteht, indem alle Kräfte aufsummiert und gleich \(m\,\ddot{y}\) gesetzt werden. |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::3._Mechanik
Note 28: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: fiDV6AZfLm
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::1._Methodik
Grundprinzip beim Aufstellen von DGln aus einer Bilanz: Die Änderungsrate einer Grösse \(y(t)\) ist die Differenz aus Zuwachsrate und Abnahmerate:
\[ {{c2::y'(t) = \text{Zuwachs}(t) - \text{Abnahme}(t)}} \]
Beide Raten sind in Einheiten pro Zeit angegeben und dürfen von \(t\) und/oder von \(y(t)\) selbst abhängen.
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::1._Methodik
Grundprinzip beim Aufstellen von DGln aus einer Bilanz: Die Änderungsrate einer Grösse \(y(t)\) ist die Differenz aus Zuwachsrate und Abnahmerate:
\[ {{c2::y'(t) = \text{Zuwachs}(t) - \text{Abnahme}(t)}} \]
Beide Raten sind in Einheiten pro Zeit angegeben und dürfen von \(t\) und/oder von \(y(t)\) selbst abhängen.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Grundprinzip</b> beim Aufstellen von DGln aus einer Bilanz: Die Änderungsrate einer Grösse \(y(t)\) ist die {{c1::Differenz aus Zuwachsrate und Abnahmerate}}:<br><br>\[ {{c2::y'(t) = \text{Zuwachs}(t) - \text{Abnahme}(t)}} \]<br>Beide Raten sind in {{c3::Einheiten pro Zeit}} angegeben und dürfen von \(t\) <b>und/oder</b> von \(y(t)\) selbst abhängen. |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::1._Methodik
Note 29: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: fsYIR[D{A1
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Bimolekulare Reaktion \(A + B \to C\) mit endlichen Anfangsmengen \(a, b\) und Reaktionskonstante \(k > 0\). Sei \(u(t)\) die Menge des Produkts \(C\) zur Zeit \(t\). Dann lautet die DGl:
\[ u'(t) = k\,(a - u(t))\,(b - u(t)) \]
Idee: Die Reaktionsrate ist proportional zum Produkt der verbleibenden Mengen \((a - u)\) von \(A\) und \((b - u)\) von \(B\), weil pro entstandenem \(C\) je ein \(A\) und ein \(B\) verbraucht werden.
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Bimolekulare Reaktion \(A + B \to C\) mit endlichen Anfangsmengen \(a, b\) und Reaktionskonstante \(k > 0\). Sei \(u(t)\) die Menge des Produkts \(C\) zur Zeit \(t\). Dann lautet die DGl:
\[ u'(t) = k\,(a - u(t))\,(b - u(t)) \]
Idee: Die Reaktionsrate ist proportional zum Produkt der verbleibenden Mengen \((a - u)\) von \(A\) und \((b - u)\) von \(B\), weil pro entstandenem \(C\) je ein \(A\) und ein \(B\) verbraucht werden.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Bimolekulare Reaktion</b> \(A + B \to C\) mit endlichen Anfangsmengen \(a, b\) und Reaktionskonstante \(k > 0\). Sei \(u(t)\) die Menge des Produkts \(C\) zur Zeit \(t\). Dann lautet die DGl:<br><br>\[ {{c1::u'(t) = k\,(a - u(t))\,(b - u(t))}} \]<br>Idee: Die Reaktionsrate ist proportional zum Produkt der {{c2::verbleibenden Mengen \((a - u)\) von \(A\) und \((b - u)\) von \(B\)}}, weil pro entstandenem \(C\) je ein \(A\) und ein \(B\) verbraucht werden. |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Note 30: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: gxV}gd66Rd
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::2._Lösungsstruktur
Satz (Superpositionsprinzip): Sind \(y_1(x)\) und \(y_2(x)\) Lösungen einer linearen, homogenen Differentialgleichung, so ist auch
\[ y(x) = C_1 y_1(x) + C_2 y_2(x), \quad C_1, C_2 \in \mathbb{R} \]eine Lösung der gleichen Differentialgleichung.
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::2._Lösungsstruktur
Satz (Superpositionsprinzip): Sind \(y_1(x)\) und \(y_2(x)\) Lösungen einer linearen, homogenen Differentialgleichung, so ist auch
\[ y(x) = C_1 y_1(x) + C_2 y_2(x), \quad C_1, C_2 \in \mathbb{R} \]eine Lösung der gleichen Differentialgleichung.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Satz (Superpositionsprinzip):</b> Sind \(y_1(x)\) und \(y_2(x)\) Lösungen einer {{c1::linearen, homogenen}} Differentialgleichung, so ist auch<br>\[ {{c2::y(x) = C_1 y_1(x) + C_2 y_2(x), \quad C_1, C_2 \in \mathbb{R}}} \]eine Lösung der gleichen Differentialgleichung. |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::2._Lösungsstruktur
Note 31: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: q;kZaA@xt9
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::1._Klassifizierung
Definition Differentialgleichung: Eine Differentialgleichung ist eine Gleichung, in welcher
die gesuchte Funktion sowie deren Ableitungen auftreten.
Bezeichnungen am Beispiel \(u'(t) = r(a - u(t))\):
- \(t\) heisst unabhängige Variable
- \(u\) heisst abhängige Variable (gesuchte Funktion)
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::1._Klassifizierung
Definition Differentialgleichung: Eine Differentialgleichung ist eine Gleichung, in welcher
die gesuchte Funktion sowie deren Ableitungen auftreten.
Bezeichnungen am Beispiel \(u'(t) = r(a - u(t))\):
- \(t\) heisst unabhängige Variable
- \(u\) heisst abhängige Variable (gesuchte Funktion)
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Definition Differentialgleichung:</b> Eine Differentialgleichung ist eine Gleichung, in welcher {{c1::die gesuchte Funktion sowie deren Ableitungen auftreten}}.<br><br>Bezeichnungen am Beispiel \(u'(t) = r(a - u(t))\):<ul><li>{{c2::\(t\) heisst <b>unabhängige Variable</b>}}</li><li>{{c3::\(u\) heisst <b>abhängige Variable</b> (gesuchte Funktion)}}</li></ul> |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::2._Lineare_homogene::1._Klassifizierung
Note 32: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: tvE6GF:g2Q
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::1._Methodik
5-Schritt-Methodik zum Aufstellen einer Differentialgleichung für eine Grösse \(y(t)\):
- Schritt 1: Veränderung in einem kleinen Zeitintervall \(\Delta t\) bilanzieren: {{c1::\(y(t + \Delta t) = y(t) + \text{Zuwachs} - \text{Abnahme}\)}}
- Schritt 2: Differenz bilden: \(\Delta y = y(t + \Delta t) - y(t)\)
- Schritt 3: Proportionale Veränderung (Differenzenquotient): {{c3::\(\dfrac{\Delta y}{\Delta t} = \dfrac{y(t + \Delta t) - y(t)}{\Delta t}\)}}
- Schritt 4: Grenzwert \(\Delta t \to 0\): {{c4::\(\dfrac{dy}{dt} = \lim\limits_{\Delta t \to 0} \dfrac{\Delta y}{\Delta t}\)}}
- Schritt 5: Differentialgleichung \(y'(t) = \dots\) zusammenfassen
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::1._Methodik
5-Schritt-Methodik zum Aufstellen einer Differentialgleichung für eine Grösse \(y(t)\):
- Schritt 1: Veränderung in einem kleinen Zeitintervall \(\Delta t\) bilanzieren: {{c1::\(y(t + \Delta t) = y(t) + \text{Zuwachs} - \text{Abnahme}\)}}
- Schritt 2: Differenz bilden: \(\Delta y = y(t + \Delta t) - y(t)\)
- Schritt 3: Proportionale Veränderung (Differenzenquotient): {{c3::\(\dfrac{\Delta y}{\Delta t} = \dfrac{y(t + \Delta t) - y(t)}{\Delta t}\)}}
- Schritt 4: Grenzwert \(\Delta t \to 0\): {{c4::\(\dfrac{dy}{dt} = \lim\limits_{\Delta t \to 0} \dfrac{\Delta y}{\Delta t}\)}}
- Schritt 5: Differentialgleichung \(y'(t) = \dots\) zusammenfassen
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>5-Schritt-Methodik</b> zum Aufstellen einer Differentialgleichung für eine Grösse \(y(t)\):<ol><li><b>Schritt 1:</b> Veränderung in einem kleinen Zeitintervall \(\Delta t\) bilanzieren: {{c1::\(y(t + \Delta t) = y(t) + \text{Zuwachs} - \text{Abnahme}\)}}</li><li><b>Schritt 2:</b> Differenz bilden: {{c2::\(\Delta y = y(t + \Delta t) - y(t)\)}}</li><li><b>Schritt 3:</b> Proportionale Veränderung (Differenzenquotient): {{c3::\(\dfrac{\Delta y}{\Delta t} = \dfrac{y(t + \Delta t) - y(t)}{\Delta t}\)}}</li><li><b>Schritt 4:</b> Grenzwert \(\Delta t \to 0\): {{c4::\(\dfrac{dy}{dt} = \lim\limits_{\Delta t \to 0} \dfrac{\Delta y}{\Delta t}\)}}</li><li><b>Schritt 5:</b> {{c5::Differentialgleichung \(y'(t) = \dots\) zusammenfassen}}</li></ol> |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::1._Methodik
Note 33: ETH::2. Semester::Analysis
Deck: ETH::2. Semester::Analysis
Note Type: Horvath Cloze
GUID: {#Z!M:@yu,
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Bevölkerungsmodell: Sei \(B(t)\) die Geburtenrate und \(T(t)\) die Sterberate (jeweils pro Zeiteinheit). Dann ist die DGl für die Bevölkerung \(y(t)\):
\[ y'(t) = B(t) - T(t) \]
Begründung: Im Intervall \(\Delta t\) gilt \(y(t+\Delta t) = y(t) + B(t)\,\Delta t - T(t)\,\Delta t\), und der Grenzwert \(\Delta t \to 0\) liefert die DGl.
Back
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Bevölkerungsmodell: Sei \(B(t)\) die Geburtenrate und \(T(t)\) die Sterberate (jeweils pro Zeiteinheit). Dann ist die DGl für die Bevölkerung \(y(t)\):
\[ y'(t) = B(t) - T(t) \]
Begründung: Im Intervall \(\Delta t\) gilt \(y(t+\Delta t) = y(t) + B(t)\,\Delta t - T(t)\,\Delta t\), und der Grenzwert \(\Delta t \to 0\) liefert die DGl.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
<b>Bevölkerungsmodell:</b> Sei \(B(t)\) die Geburtenrate und \(T(t)\) die Sterberate (jeweils pro Zeiteinheit). Dann ist die DGl für die Bevölkerung \(y(t)\):<br><br>\[ {{c1::y'(t) = B(t) - T(t)}} \]<br>Begründung: Im Intervall \(\Delta t\) gilt {{c2::\(y(t+\Delta t) = y(t) + B(t)\,\Delta t - T(t)\,\Delta t\)}}, und der Grenzwert \(\Delta t \to 0\) liefert die DGl. |
Tags:
ETH::2._Semester::Analysis::6._Differentialgleichungen::1._Aufstellen::2._Modelle
Note 34: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: $JRc9>k3KE
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Implementation of a semaphore
without spinning (with a blocking queue \(Q_S\)):
acquire(S): release(S):
if S > 0: dec(S) if Q_S == \(\emptyset\): inc(S)
else: put(Q_S, self); else: get(Q_S, p);
block(self) unblock(p)The condition test plus queue operation must be
atomic (e.g. under an internal lock).
release only increments S if no one is waiting: otherwise it directly unblocks a waiting process without
S ever becoming positive.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Implementation of a semaphore
without spinning (with a blocking queue \(Q_S\)):
acquire(S): release(S):
if S > 0: dec(S) if Q_S == \(\emptyset\): inc(S)
else: put(Q_S, self); else: get(Q_S, p);
block(self) unblock(p)The condition test plus queue operation must be
atomic (e.g. under an internal lock).
release only increments S if no one is waiting: otherwise it directly unblocks a waiting process without
S ever becoming positive.
Advantage over busy-wait: waiting threads consume no CPU. The price is context-switch overhead, which only pays off once waits are long enough to dwarf it (short critical sections may still favour spinning).
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Implementation of a semaphore {{c1::without spinning (with a blocking queue \(Q_S\))}}: <pre>acquire(S): release(S):
if S > 0: dec(S) if Q_S == \(\emptyset\): inc(S)
else: put(Q_S, self); else: get(Q_S, p);
block(self) unblock(p)</pre>The condition test plus queue operation must be {{c2::atomic}} (e.g. under an internal lock). {{c3::<code>release</code> only increments <code>S</code> if no one is waiting}}: otherwise it directly unblocks a waiting process without <code>S</code> ever becoming positive. |
| Extra |
|
Advantage over busy-wait: waiting threads consume no CPU. The price is context-switch overhead, which only pays off once waits are long enough to dwarf it (short critical sections may still favour spinning). |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Note 35: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: +7_a8+a@b@
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
In the 2nd reusable-barrier trial, the release(mutex) is moved to after the release(barrier) on the entry side (and analogously on the exit side). It still fails because a single process can lap the others: while \(n-1\) processes are still in the post-barrier region, one fast process re-enters the entry section, increments count, and could even reach count == n a second time before the others have finished the first round. Violated invariant: "even when a single process has passed the barrier, barrier = 0": the lapping process leaves barrier open behind it.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
In the 2nd reusable-barrier trial, the release(mutex) is moved to after the release(barrier) on the entry side (and analogously on the exit side). It still fails because a single process can lap the others: while \(n-1\) processes are still in the post-barrier region, one fast process re-enters the entry section, increments count, and could even reach count == n a second time before the others have finished the first round. Violated invariant: "even when a single process has passed the barrier, barrier = 0": the lapping process leaves barrier open behind it.
The fundamental issue: a single semaphore cannot serve as both "all have arrived" and "all have left". Two semaphores in sequence are needed.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
In the 2nd reusable-barrier trial, the <code>release(mutex)</code> is moved to <em>after</em> the <code>release(barrier)</code> on the entry side (and analogously on the exit side). It still fails because {{c1::a single process can lap the others: while \(n-1\) processes are still in the post-barrier region, one fast process re-enters the entry section, increments <code>count</code>, and could even reach <code>count == n</code> a second time before the others have finished the first round}}. Violated invariant: {{c2::"even when a single process has passed the barrier, <code>barrier = 0</code>": the lapping process leaves <code>barrier</code> open behind it}}. |
| Extra |
|
The fundamental issue: a single semaphore cannot serve as both "all have arrived" and "all have left". Two semaphores in sequence are needed. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Note 36: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: -T60qL&2-|
modified
Before
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
The three conditions for a correct critical-section solution according to Ben-Ari are mutual exclusion (statements from CSes of different processes must not interleave), freedom from deadlock (if some processes are trying to enter a CS, at least one must eventually succeed), and freedom from starvation (any process trying to enter its CS must eventually succeed).
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
The three conditions for a correct critical-section solution according to Ben-Ari are mutual exclusion (statements from CSes of different processes must not interleave), freedom from deadlock (if some processes are trying to enter a CS, at least one must eventually succeed), and freedom from starvation (any process trying to enter its CS must eventually succeed).
Hierarchy: starvation freedom \(\Rightarrow\) deadlock freedom (if every individual gets through, then certainly some individual gets through), but not the converse.
After
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
The three conditions for a correct critical-section solution according to Ben-Ari are:
- Mutual exclusion (statements from CSes of different processes must not interleave).
- Freedom from deadlock (if some processes are trying to enter a CS, at least one must eventually succeed).
- Freedom from starvation (any process trying to enter its CS must eventually succeed).
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
The three conditions for a correct critical-section solution according to Ben-Ari are:
- Mutual exclusion (statements from CSes of different processes must not interleave).
- Freedom from deadlock (if some processes are trying to enter a CS, at least one must eventually succeed).
- Freedom from starvation (any process trying to enter its CS must eventually succeed).
Hierarchy: starvation freedom \(\Rightarrow\) deadlock freedom (if every individual gets through, then certainly some individual gets through), but not the converse.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
The three conditions for a correct critical-section solution according to Ben-Ari are {{c1::mutual exclusion (statements from CSes of different processes must not interleave)}}, {{c2::freedom from deadlock (if some processes are trying to enter a CS, at least one must eventually succeed)}}, and {{c3::freedom from starvation (any process trying to enter its CS must eventually succeed)}}. |
The three conditions for a correct critical-section solution according to Ben-Ari are:<br><ol><li>{{c1::Mutual exclusion (statements from CSes of different processes must not interleave)}}.</li><li>{{c2::Freedom from deadlock (if some processes are trying to enter a CS, at least one must eventually succeed)}}.</li><li>{{c3::Freedom from starvation (any process trying to enter its CS must eventually succeed)}}.</li></ol> |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
Note 37: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: /J$dsYJ
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
A barrier synchronises a number \(n\) of processes such that no process passes the barrier until all \(n\) of them have reached it.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
A barrier synchronises a number \(n\) of processes such that no process passes the barrier until all \(n\) of them have reached it.
Unlike a rendezvous (which is for exactly two processes), a barrier generalises to arbitrarily many. This fits BSP naturally: between any two supersteps stands a barrier.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
A {{c1::barrier}} synchronises {{c2::a number \(n\) of processes such that no process passes the barrier until all \(n\) of them have reached it}}. |
| Extra |
|
Unlike a rendezvous (which is for exactly two processes), a barrier generalises to arbitrarily many. This fits BSP naturally: between any two supersteps stands a barrier. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Note 38: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: 1*Jyz+ZJLF
modified
Before
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
When constructing mutex algorithms from atomic registers, three assumptions are made:
- atomic reads and writes of primitive-type variables
- no reorderings of read/write sequences (not true in practice; assumed here for simplicity)
- threads that enter a critical section eventually leave it.
About progress
outside the critical section, no assumption is made.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
When constructing mutex algorithms from atomic registers, three assumptions are made:
- atomic reads and writes of primitive-type variables
- no reorderings of read/write sequences (not true in practice; assumed here for simplicity)
- threads that enter a critical section eventually leave it.
About progress
outside the critical section, no assumption is made.
Threads may therefore stall, die, or pause arbitrarily long outside a CS. This matters for arguments like starvation freedom: an algorithm must not rely on the "other" thread continuing to make progress.
After
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
When constructing mutex algorithms from atomic registers, three assumptions are made:
- atomic reads and writes of primitive-type variables
- no reorderings of read/write sequences (not true in practice; assumed here for simplicity)
- threads that enter a critical section eventually leave it.
About progress outside the critical section,
no assumption is made.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
When constructing mutex algorithms from atomic registers, three assumptions are made:
- atomic reads and writes of primitive-type variables
- no reorderings of read/write sequences (not true in practice; assumed here for simplicity)
- threads that enter a critical section eventually leave it.
About progress outside the critical section,
no assumption is made.
Threads may therefore stall, die, or pause arbitrarily long outside a CS. This matters for arguments like starvation freedom: an algorithm must not rely on the "other" thread continuing to make progress.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
When constructing mutex algorithms from atomic registers, three assumptions are made: <br><ol><li>{{c1::atomic reads and writes of primitive-type variables}}</li><li>{{c2::no reorderings of read/write sequences (not true in practice; assumed here for simplicity)}} </li><li>{{c3::threads that enter a critical section eventually leave it}}. </li></ol>About progress {{c4::outside the critical section, no assumption is made}}.<br> |
When constructing mutex algorithms from atomic registers, three assumptions are made: <br><ol><li>{{c1::atomic reads and writes of primitive-type variables}}</li><li>{{c2::no reorderings of read/write sequences (not true in practice; assumed here for simplicity)}} </li><li>{{c3::threads that enter a critical section eventually leave it}}. </li></ol>About progress outside the critical section, {{c4::no assumption is made}}.<br> |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
Note 39: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: 43#$Fc|Xs+
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Two-phase barrier solution: with
mutex=1, barrier1=0, barrier2=1, count=0,
acquire(mutex)
count++
if (count==n) { acquire(barrier2); release(barrier1); }
release(mutex)
acquire(barrier1); release(barrier1); // phase 1
acquire(mutex)
count--
if (count==0) { acquire(barrier1); release(barrier2); }
release(mutex)
acquire(barrier2); release(barrier2); // phase 2Idea:
two semaphores act as alternating gates: the \(n\)-th arriver flips barrier1 open and barrier2 closed; the last leaver flips them back. Between phases the invariant is
barrier1 = 1 and barrier2 = 0 for all processes (and after phase 2: barrier1 = 0, barrier2 = 1).
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Two-phase barrier solution: with
mutex=1, barrier1=0, barrier2=1, count=0,
acquire(mutex)
count++
if (count==n) { acquire(barrier2); release(barrier1); }
release(mutex)
acquire(barrier1); release(barrier1); // phase 1
acquire(mutex)
count--
if (count==0) { acquire(barrier1); release(barrier2); }
release(mutex)
acquire(barrier2); release(barrier2); // phase 2Idea:
two semaphores act as alternating gates: the \(n\)-th arriver flips barrier1 open and barrier2 closed; the last leaver flips them back. Between phases the invariant is
barrier1 = 1 and barrier2 = 0 for all processes (and after phase 2: barrier1 = 0, barrier2 = 1).
The barrier is now safely reusable: each iteration ends with the same initial state (count = 0, one barrier closed, one open). In practice this is very slow; specialised x86 barriers (e.g. spiral.net) can be many times faster.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Two-phase barrier solution: with <code>mutex=1, barrier1=0, barrier2=1, count=0</code>, <pre>acquire(mutex)
count++
if (count==n) { acquire(barrier2); release(barrier1); }
release(mutex)
acquire(barrier1); release(barrier1); // phase 1
acquire(mutex)
count--
if (count==0) { acquire(barrier1); release(barrier2); }
release(mutex)
acquire(barrier2); release(barrier2); // phase 2</pre>Idea: {{c1::two semaphores act as alternating gates: the \(n\)-th arriver flips <code>barrier1</code> open and <code>barrier2</code> closed; the last leaver flips them back}}. Between phases the invariant is {{c2::<code>barrier1 = 1</code> and <code>barrier2 = 0</code> for all processes (and after phase 2: <code>barrier1 = 0</code>, <code>barrier2 = 1</code>)}}. |
| Extra |
|
The barrier is now safely reusable: each iteration ends with the same initial state (<code>count = 0</code>, one barrier closed, one open). In practice this is very slow; specialised x86 barriers (e.g. spiral.net) can be many times faster. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Note 40: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: 6>tVnB+D6%
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Correct (one-shot) barrier with semaphores
mutex = 1,
barrier = 0 and integer
count = 0:
acquire(mutex)
count++
release(mutex)
if (count == n) release(barrier)
acquire(barrier)
release(barrier)
The mutex protects
the race on count++; the trailing
acquire(barrier); release(barrier); is called a
turnstile and ensures that
each thread that gets through immediately admits the next, so all \(n\) threads pass in sequence.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Correct (one-shot) barrier with semaphores
mutex = 1,
barrier = 0 and integer
count = 0:
acquire(mutex)
count++
release(mutex)
if (count == n) release(barrier)
acquire(barrier)
release(barrier)
The mutex protects
the race on count++; the trailing
acquire(barrier); release(barrier); is called a
turnstile and ensures that
each thread that gets through immediately admits the next, so all \(n\) threads pass in sequence.
After one run, count = n and barrier = 1: the barrier is not reusable (a reusable version needs a second phase, often called a "two-phase barrier"). Exactly one thread (the \(n\)-th) calls release(barrier), and the turnstile passes the token along.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Correct (one-shot) barrier with semaphores <code>mutex = 1</code>, <code>barrier = 0</code> and integer <code>count = 0</code>: <pre>acquire(mutex)
count++
release(mutex)
if (count == n) release(barrier)
acquire(barrier)
release(barrier)</pre>The mutex protects {{c1::the race on <code>count++</code>}}; the trailing <code>acquire(barrier); release(barrier);</code> is called a {{c2::turnstile}} and ensures that {{c3::each thread that gets through immediately admits the next, so all \(n\) threads pass in sequence}}. |
| Extra |
|
After one run, <code>count = n</code> and <code>barrier = 1</code>: the barrier is not reusable (a reusable version needs a second phase, often called a "two-phase barrier"). Exactly one thread (the \(n\)-th) calls <code>release(barrier)</code>, and the turnstile passes the token along. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Note 41: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: 8rwYF+/ZRs
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::Terminology
Starvation denotes the repeated but unsuccessful attempt of a recently unblocked process to continue its execution.
Back
ETH::2._Semester::PProg::Terminology
Starvation denotes the repeated but unsuccessful attempt of a recently unblocked process to continue its execution.
Contrast with deadlock: under deadlock the whole system makes no progress; under starvation the system does make progress, but a particular process never gets through. Starvation is a liveness violation.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
{{c1::Starvation}} denotes {{c2::the repeated but unsuccessful attempt of a recently unblocked process to continue its execution}}. |
| Extra |
|
Contrast with deadlock: under deadlock the whole system makes no progress; under starvation the system does make progress, but a particular process never gets through. Starvation is a liveness violation. |
Tags:
ETH::2._Semester::PProg::Terminology
Note 42: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID:
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Scaled dot product \(x = (a^T \cdot d) \cdot z\) with partial sums \(x_A, x_B\) on two threads: with locks (lock(); x = x + x_A; unlock(); in both threads) it is unclear when \(x\) is finished. With a semaphore \(S\) initialised to \(0\), the order can be enforced: thread A computes x = x + x_A and then calls release(S); thread B does acquire(S) first, then x = x + x_B, then x = x*z. This guarantees that A adds before B.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Scaled dot product \(x = (a^T \cdot d) \cdot z\) with partial sums \(x_A, x_B\) on two threads: with locks (lock(); x = x + x_A; unlock(); in both threads) it is unclear when \(x\) is finished. With a semaphore \(S\) initialised to \(0\), the order can be enforced: thread A computes x = x + x_A and then calls release(S); thread B does acquire(S) first, then x = x + x_B, then x = x*z. This guarantees that A adds before B.
This is exactly what locks cannot deliver: not only mutual exclusion, but a concrete ordering between threads. The trick with initial value \(0\): the first acquire blocks until a release unblocks it: the semaphore is used as a signal, not as a mutex.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Scaled dot product \(x = (a^T \cdot d) \cdot z\) with partial sums \(x_A, x_B\) on two threads: with locks ({{c1::<code>lock(); x = x + x_A; unlock();</code> in both threads}}) it is unclear <i>when</i> \(x\) is finished. With a semaphore \(S\) initialised to \(0\), the order can be enforced: {{c2::thread A computes <code>x = x + x_A</code> and then calls <code>release(S)</code>}}; {{c2::thread B does <code>acquire(S)</code> first, then <code>x = x + x_B</code>, then <code>x = x*z</code>}}. This guarantees that A adds before B. |
| Extra |
|
This is exactly what locks cannot deliver: not only mutual exclusion, but a concrete ordering between threads. The trick with initial value \(0\): the first <code>acquire</code> blocks until a <code>release</code> unblocks it: the semaphore is used as a <em>signal</em>, not as a mutex. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Note 43: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: >^UKYB#lC@
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
A naive reusable barrier extends the one-shot barrier with a symmetric "second half"
acquire(mutex); count--; release(mutex);
if (count==0) acquire(barrier);
after the turnstile, intended to reset
count and
barrier. It is broken because
the invariant "after all processes have passed, barrier = 0" is violated: release(barrier) can be executed multiple times across iterations before any thread reaches the resetting acquire(barrier), so barrier drifts to \(2, 3, \dots\), and
the if (count == 0) acquire(barrier) check happens outside the mutex, so it cannot reliably restore the semaphore to 0 in the presence of fast re-entrants.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
A naive reusable barrier extends the one-shot barrier with a symmetric "second half"
acquire(mutex); count--; release(mutex);
if (count==0) acquire(barrier);
after the turnstile, intended to reset
count and
barrier. It is broken because
the invariant "after all processes have passed, barrier = 0" is violated: release(barrier) can be executed multiple times across iterations before any thread reaches the resetting acquire(barrier), so barrier drifts to \(2, 3, \dots\), and
the if (count == 0) acquire(barrier) check happens outside the mutex, so it cannot reliably restore the semaphore to 0 in the presence of fast re-entrants.
Concrete scheduling: thread A finishes phase 1 with count = 1; meanwhile B and C race into the next iteration, both increment count back up, hit count == n, and each calls release(barrier). The semaphore is no longer a clean 0/1 toggle. The fix is a proper two-phase split with separate semaphores for the two halves.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
A naive reusable barrier extends the one-shot barrier with a symmetric "second half" <pre>acquire(mutex); count--; release(mutex);
if (count==0) acquire(barrier);</pre>after the turnstile, intended to reset <code>count</code> and <code>barrier</code>. It is broken because {{c1::the invariant "after all processes have passed, <code>barrier = 0</code>" is violated: <code>release(barrier)</code> can be executed multiple times across iterations before any thread reaches the resetting <code>acquire(barrier)</code>, so <code>barrier</code> drifts to \(2, 3, \dots\)}}, and {{c2::the <code>if (count == 0) acquire(barrier)</code> check happens outside the mutex, so it cannot reliably restore the semaphore to 0 in the presence of fast re-entrants}}. |
| Extra |
|
Concrete scheduling: thread A finishes phase 1 with <code>count = 1</code>; meanwhile B and C race into the next iteration, both increment <code>count</code> back up, hit <code>count == n</code>, and each calls <code>release(barrier)</code>. The semaphore is no longer a clean 0/1 toggle. The fix is a proper two-phase split with separate semaphores for the two halves. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Note 44: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: >aq{oB;vc7
modified
Before
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
The structure of the critical-section problem per process inside an infinite loop is: non-critical section \(\to\) preprotocol \(\to\) critical section \(\to\) postprotocol.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
The structure of the critical-section problem per process inside an infinite loop is: non-critical section \(\to\) preprotocol \(\to\) critical section \(\to\) postprotocol.
Preprotocol = entry code (lock acquire). Postprotocol = exit code (lock release). Only global variables are shared between processes; local variables are private per process.
After
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
The structure of the critical-section problem per process inside an infinite loop is:
non-critical section \(\to\) preprotocol \(\to\) critical section \(\to\) postprotocol.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
The structure of the critical-section problem per process inside an infinite loop is:
non-critical section \(\to\) preprotocol \(\to\) critical section \(\to\) postprotocol.
Preprotocol = entry code (lock acquire). Postprotocol = exit code (lock release). Only global variables are shared between processes; local variables are private per process.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
The structure of the critical-section problem per process inside an infinite loop is: {{c1::non-critical section}} \(\to\) {{c2::preprotocol}} \(\to\) {{c3::critical section}} \(\to\) {{c4::postprotocol}}. |
The structure of the critical-section problem per process inside an infinite loop is: <br>{{c1::non-critical section}} \(\to\) {{c1::preprotocol}} \(\to\) {{c1::critical section}} \(\to\) {{c1::postprotocol}}. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
Note 45: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: ?Sz*VQ/MVU
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::12._Lock_and_Condition
Disadvantage of the plain producer-consumer with Lock + Condition: signal() is called on every enqueue and dequeue, even when no thread is currently waiting on that condition (a wasted call into the runtime). Dijkstra's Sleeping Barber variant adds two counters \(m\) and \(n\) with the semantics \(m \leq 0 \Leftrightarrow\) buffer full and \(-m\) producers are waiting and \(n \leq 0 \Leftrightarrow\) buffer empty and \(-n\) consumers are waiting, so signals are issued only when someone is actually waiting.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::12._Lock_and_Condition
Disadvantage of the plain producer-consumer with Lock + Condition: signal() is called on every enqueue and dequeue, even when no thread is currently waiting on that condition (a wasted call into the runtime). Dijkstra's Sleeping Barber variant adds two counters \(m\) and \(n\) with the semantics \(m \leq 0 \Leftrightarrow\) buffer full and \(-m\) producers are waiting and \(n \leq 0 \Leftrightarrow\) buffer empty and \(-n\) consumers are waiting, so signals are issued only when someone is actually waiting.
Initial values: \(n = 0\) (buffer empty, no waiters), \(m = \text{size} - 1\) (one fewer free slot than capacity, matching the unused-slot trick of the underlying ring buffer). The barber metaphor: the customer (consumer) waits if no client is in the chair; the barber (producer) sleeps if no chair is free.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Disadvantage of the plain producer-consumer with <code>Lock</code> + <code>Condition</code>: {{c1::<code>signal()</code> is called on every <code>enqueue</code> and <code>dequeue</code>, even when no thread is currently waiting on that condition (a wasted call into the runtime)}}. Dijkstra's <em>Sleeping Barber</em> variant adds {{c2::two counters \(m\) and \(n\)}} with the semantics {{c3::\(m \leq 0 \Leftrightarrow\) buffer full and \(-m\) producers are waiting}} and {{c3::\(n \leq 0 \Leftrightarrow\) buffer empty and \(-n\) consumers are waiting}}, so signals are issued only when someone is actually waiting. |
| Extra |
|
Initial values: \(n = 0\) (buffer empty, no waiters), \(m = \text{size} - 1\) (one fewer free slot than capacity, matching the unused-slot trick of the underlying ring buffer). The barber metaphor: the customer (consumer) waits if no client is in the chair; the barber (producer) sleeps if no chair is free. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::12._Lock_and_Condition
Note 46: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: F1>/n6vs8v
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
A monitor is an abstract data structure equipped with a set of operations that run in mutual exclusion, plus a mechanism to wait on conditions inside the monitor. Invented by Tony Hoare and Per Brinch Hansen (1974).
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
A monitor is an abstract data structure equipped with a set of operations that run in mutual exclusion, plus a mechanism to wait on conditions inside the monitor. Invented by Tony Hoare and Per Brinch Hansen (1974).
Beyond mutual exclusion, a monitor must let a thread that finds a condition unsatisfied release the monitor lock, wait for the condition, and be signalled when it becomes true, all without busy-waiting.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
A {{c1::monitor}} is {{c2::an abstract data structure equipped with a set of operations that run in mutual exclusion}}, plus a mechanism to wait on conditions inside the monitor. Invented by {{c3::Tony Hoare and Per Brinch Hansen (1974)}}. |
| Extra |
|
Beyond mutual exclusion, a monitor must let a thread that finds a condition unsatisfied release the monitor lock, wait for the condition, and be signalled when it becomes true, all without busy-waiting. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
Note 47: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: IglAO#3E9?
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::7._Deadlock_Avoidance
Two cases in which deadlock prevention by a fixed lock order is straightforward: different object types: document a fixed order between the types (e.g. "when moving an item from the hashtable to the work queue, never try to acquire the queue lock while holding the hashtable lock") and objects in an acyclic data structure: use the structure itself to determine an order (e.g. "if holding a tree node's lock, do not acquire other tree nodes' locks unless they are children").
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::7._Deadlock_Avoidance
Two cases in which deadlock prevention by a fixed lock order is straightforward: different object types: document a fixed order between the types (e.g. "when moving an item from the hashtable to the work queue, never try to acquire the queue lock while holding the hashtable lock") and objects in an acyclic data structure: use the structure itself to determine an order (e.g. "if holding a tree node's lock, do not acquire other tree nodes' locks unless they are children").
Both cases break the Coffman "circular wait" condition by imposing a total order on locks. The hard case (like transferTo or StringBuffer.append) is when two objects of the same type with no natural ordering are involved.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Two cases in which deadlock prevention by a fixed lock order is straightforward: {{c1::different object types: document a fixed order between the types (e.g. "when moving an item from the hashtable to the work queue, never try to acquire the queue lock while holding the hashtable lock")}} and {{c2::objects in an acyclic data structure: use the structure itself to determine an order (e.g. "if holding a tree node's lock, do not acquire other tree nodes' locks unless they are children")}}. |
| Extra |
|
Both cases break the Coffman "circular wait" condition by imposing a total order on locks. The hard case (like <code>transferTo</code> or <code>StringBuffer.append</code>) is when two objects of the same type with no natural ordering are involved. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::7._Deadlock_Avoidance
Note 48: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: Jj5bulRE#&
modified
Before
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
In the 1st-try mutex
p2: while(wantq);
p3: wantp = true;
p4: critical section
the order "first wait for the neighbour, then set my own flag" violates
mutual exclusion, because {{c2::both threads can leave their
while with
wantp{=}wantq{=}false before either of them sets its flag}}.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
In the 1st-try mutex
p2: while(wantq);
p3: wantp = true;
p4: critical section
the order "first wait for the neighbour, then set my own flag" violates
mutual exclusion, because {{c2::both threads can leave their
while with
wantp{=}wantq{=}false before either of them sets its flag}}.
Both threads enter the CS together; visible as state \((p4, q4, true, true)\) in the state-space diagram.
Naive fix: set the flag before the check. That solves ME but creates new problems (deadlock/livelock); see Dekker / Peterson.
After
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers

Here the order "first wait for the neighbour, then set my own flag" violates
mutual exclusion, because {{c2::both threads can leave their
while with
wantp{=}wantq{=}false before either of them sets its flag}}.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers

Here the order "first wait for the neighbour, then set my own flag" violates
mutual exclusion, because {{c2::both threads can leave their
while with
wantp{=}wantq{=}false before either of them sets its flag}}.
Both threads enter the CS together; visible as state \((p4, q4, true, true)\) in the state-space diagram.
Naive fix: set the flag before the check. That solves ME but creates new problems (deadlock/livelock); see Dekker / Peterson.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
In the 1st-try mutex <pre>p2: while(wantq);
p3: wantp = true;
p4: critical section</pre> the order "first wait for the neighbour, then set my own flag" violates {{c1::mutual exclusion}}, because {{c2::both threads can leave their <code>while</code> with <code>wantp{=}wantq{=}false</code> before either of them sets its flag}}. |
<img src="paste-2c297c3fe3ab4f7a63914ae8ad4be81fa93d9e11.jpg"><br><br>Here the order "first wait for the neighbour, then set my own flag" violates {{c1::mutual exclusion}}, because {{c2::both threads can leave their <code>while</code> with <code>wantp{=}wantq{=}false</code> before either of them sets its flag}}. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::5._Locks_with_Atomic_Registers
Note 49: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: L8nAd_#p<^
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
A rendezvous is a location in code at which two processes \(P\) and \(Q\) each wait for the other to arrive before either continues. It synchronises two threads at a common point.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
A rendezvous is a location in code at which two processes \(P\) and \(Q\) each wait for the other to arrive before either continues. It synchronises two threads at a common point.
Implementation with two semaphores P_Arrived and Q_Arrived (both initialised to 0): each thread releases "its" semaphore and acquires the other one.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
A {{c1::rendezvous}} is {{c2::a location in code at which two processes \(P\) and \(Q\) each wait for the other to arrive before either continues}}. It synchronises two threads at a common point. |
| Extra |
|
Implementation with two semaphores <code>P_Arrived</code> and <code>Q_Arrived</code> (both initialised to 0): each thread releases "its" semaphore and acquires the other one. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Note 50: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: LQq9qK6Fz1
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
Naive synchronised producer-consumer queue
synchronized void enqueue(long item) {
while (isFull()) ; // wait
doEnqueue(item);
}is broken because
the busy-wait holds the monitor lock the entire time, so no other thread (including the consumer that would make space) can enter the object: the producer spins forever and the consumer blocks at the entry. Effectively a
deadlock between the spinning producer and any thread that would change the condition.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
Naive synchronised producer-consumer queue
synchronized void enqueue(long item) {
while (isFull()) ; // wait
doEnqueue(item);
}is broken because
the busy-wait holds the monitor lock the entire time, so no other thread (including the consumer that would make space) can enter the object: the producer spins forever and the consumer blocks at the entry. Effectively a
deadlock between the spinning producer and any thread that would change the condition.
Lesson: any "wait until condition" pattern under a held lock must release the lock while waiting and reacquire it before re-checking. That is exactly what wait() / await() do.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Naive synchronised producer-consumer queue <pre>synchronized void enqueue(long item) {
while (isFull()) ; // wait
doEnqueue(item);
}</pre>is broken because {{c1::the busy-wait holds the monitor lock the entire time, so no other thread (including the consumer that would make space) can enter the object}}: the producer spins forever and the consumer blocks at the entry. Effectively a {{c2::deadlock between the spinning producer and any thread that would change the condition}}. |
| Extra |
|
Lesson: any "wait until condition" pattern under a held lock must <em>release</em> the lock while waiting and reacquire it before re-checking. That is exactly what <code>wait()</code> / <code>await()</code> do. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
Note 51: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: Lf?|c7TXKB
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Four invariants a correct barrier must satisfy: each of the processes eventually reaches the acquire statement; the barrier opens iff all processes have reached the barrier; count gives the number of processes that have passed the barrier; once all processes have reached the barrier, all waiting processes can continue.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Four invariants a correct barrier must satisfy: each of the processes eventually reaches the acquire statement; the barrier opens iff all processes have reached the barrier; count gives the number of processes that have passed the barrier; once all processes have reached the barrier, all waiting processes can continue.
The naive 1st-try implementation violates the latter two: the race on count++ breaks (3), and the single release on a 0-initialised semaphore breaks (4).
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Four invariants a correct barrier must satisfy: {{c1::each of the processes eventually reaches the <code>acquire</code> statement}}; {{c2::the barrier opens iff all processes have reached the barrier}}; {{c3::<code>count</code> gives the number of processes that have passed the barrier}}; {{c4::once all processes have reached the barrier, all waiting processes can continue}}. |
| Extra |
|
The naive 1st-try implementation violates the latter two: the race on <code>count++</code> breaks (3), and the single <code>release</code> on a 0-initialised semaphore breaks (4). |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Note 52: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: MbxyJU2Qdg
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
Replacing the busy-wait with Thread.sleep(timeout) outside the synchronized block (while(true){ synchronized(this){ if (!isFull()){ doEnqueue(...); return; }} sleep(t); }) fixes the deadlock but has no good value for timeout: too short wastes CPU on repeated re-acquisition, too long adds latency between the queue freeing up and the producer noticing. The real wish is to be notified exactly when the condition becomes true (i.e. when a consumer dequeues), not to poll.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
Replacing the busy-wait with Thread.sleep(timeout) outside the synchronized block (while(true){ synchronized(this){ if (!isFull()){ doEnqueue(...); return; }} sleep(t); }) fixes the deadlock but has no good value for timeout: too short wastes CPU on repeated re-acquisition, too long adds latency between the queue freeing up and the producer noticing. The real wish is to be notified exactly when the condition becomes true (i.e. when a consumer dequeues), not to poll.
This motivates monitors / wait-notify: instead of polling, the producer waits on a condition and the consumer signals it after dequeuing.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Replacing the busy-wait with <code>Thread.sleep(timeout)</code> outside the synchronized block (<code>while(true){ synchronized(this){ if (!isFull()){ doEnqueue(...); return; }} sleep(t); }</code>) fixes the deadlock but {{c1::has no good value for <code>timeout</code>}}: too short wastes CPU on repeated re-acquisition, too long adds latency between the queue freeing up and the producer noticing. The real wish is {{c2::to be notified exactly when the condition becomes true (i.e. when a consumer dequeues), not to poll}}. |
| Extra |
|
This motivates monitors / wait-notify: instead of polling, the producer waits on a condition and the consumer signals it after dequeuing. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
Note 53: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: P5lCo*-DG/
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::7._Deadlock_Avoidance
Race conditions vs. deadlocks: race conditions, once you understand where they can occur, are relatively easy to handle with good programming practice and rules. Deadlock, by contrast, is the dominant problem of reasonably complex concurrent programs and must therefore be anticipated from the start.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::7._Deadlock_Avoidance
Race conditions vs. deadlocks: race conditions, once you understand where they can occur, are relatively easy to handle with good programming practice and rules. Deadlock, by contrast, is the dominant problem of reasonably complex concurrent programs and must therefore be anticipated from the start.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Race conditions vs. deadlocks: {{c1::race conditions, once you understand where they can occur, are relatively easy to handle with good programming practice and rules}}. {{c2::Deadlock, by contrast, is the dominant problem of reasonably complex concurrent programs and must therefore be anticipated from the start}}. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::7._Deadlock_Avoidance
Note 54: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: S1F/!41?Q?
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::12._Lock_and_Condition
Sleeping-Barber producer-consumer signalling logic:
enqueue(x): m--; // claim a slot in advance
if (m < 0) while (isFull()) notFull.await();
doEnqueue(x);
n++;
if (n <= 0) notEmpty.signal();
dequeue(): n--;
if (n < 0) while (isEmpty()) notEmpty.await();
doDequeue();
m++;
if (m <= 0) notFull.signal();The decrement-first / check-negative pattern:
m-- followed by if (m < 0) reserves a slot and detects "buffer was full" before waiting;
n++ followed by if (n <= 0) means "after my insert there is at least one consumer still waiting", so signal exactly then, saving the call when n > 0 (no one is waiting).
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::12._Lock_and_Condition
Sleeping-Barber producer-consumer signalling logic:
enqueue(x): m--; // claim a slot in advance
if (m < 0) while (isFull()) notFull.await();
doEnqueue(x);
n++;
if (n <= 0) notEmpty.signal();
dequeue(): n--;
if (n < 0) while (isEmpty()) notEmpty.await();
doDequeue();
m++;
if (m <= 0) notFull.signal();The decrement-first / check-negative pattern:
m-- followed by if (m < 0) reserves a slot and detects "buffer was full" before waiting;
n++ followed by if (n <= 0) means "after my insert there is at least one consumer still waiting", so signal exactly then, saving the call when n > 0 (no one is waiting).
The asymmetry < 0 vs <= 0 on the wait side vs the signal side is intentional: at the moment of my own increment, my counter has just become +1 if I was the only waiter, so the condition for "someone else is still waiting" is <= 0.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Sleeping-Barber producer-consumer signalling logic: <pre>enqueue(x): m--; // claim a slot in advance
if (m < 0) while (isFull()) notFull.await();
doEnqueue(x);
n++;
if (n <= 0) notEmpty.signal();
dequeue(): n--;
if (n < 0) while (isEmpty()) notEmpty.await();
doDequeue();
m++;
if (m <= 0) notFull.signal();</pre>The decrement-first / check-negative pattern: {{c1::<code>m--</code> followed by <code>if (m < 0)</code> reserves a slot and detects "buffer was full" before waiting}}; {{c2::<code>n++</code> followed by <code>if (n <= 0)</code> means "after my insert there is at least one consumer still waiting", so signal exactly then, saving the call when <code>n > 0</code> (no one is waiting)}}. |
| Extra |
|
The asymmetry <code>< 0</code> vs <code><= 0</code> on the wait side vs the signal side is intentional: at the moment of <em>my own</em> increment, my counter has just become <code>+1</code> if I was the only waiter, so the condition for "someone else is still waiting" is <code><= 0</code>. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::12._Lock_and_Condition
Note 55: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: SSYmrji*fb
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
Why semaphores (and raw locks) are problematic for non-trivial coordination: they are unstructured: correct use requires a high level of programmer discipline (the right acquire order, the right release on every path, including exception paths) and it is easy to introduce deadlocks. What we want instead: a lock that we can temporarily escape from while waiting on a condition, and that signals us when the condition can become true.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
Why semaphores (and raw locks) are problematic for non-trivial coordination: they are unstructured: correct use requires a high level of programmer discipline (the right acquire order, the right release on every path, including exception paths) and it is easy to introduce deadlocks. What we want instead: a lock that we can temporarily escape from while waiting on a condition, and that signals us when the condition can become true.
This wish list defines a monitor: a lock plus condition variables that atomically release the lock on wait and reacquire it on signal.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Why semaphores (and raw locks) are problematic for non-trivial coordination: {{c1::they are unstructured: correct use requires a high level of programmer discipline (the right acquire order, the right release on every path, including exception paths) and it is easy to introduce deadlocks}}. What we want instead: {{c2::a lock that we can temporarily escape from while waiting on a condition, and that signals us when the condition can become true}}. |
| Extra |
|
This wish list defines a monitor: a lock plus condition variables that atomically release the lock on wait and reacquire it on signal. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
Note 56: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: SX-B$lpC!#
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
A semaphore initialised to 1 (sem_mutex = Semaphore(1)) acts as a lock: lock() is sem_mutex.acquire() and unlock() is sem_mutex.release(). In general the value means: \(1\) is unlocked, \(0\) is locked, \(x > 0\) means \(x\) threads will be let into the "critical section".
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
A semaphore initialised to 1 (sem_mutex = Semaphore(1)) acts as a lock: lock() is sem_mutex.acquire() and unlock() is sem_mutex.release(). In general the value means: \(1\) is unlocked, \(0\) is locked, \(x > 0\) means \(x\) threads will be let into the "critical section".
A semaphore with initial value \(k > 1\) is therefore a generalised lock that admits up to \(k\) threads concurrently (a counting semaphore). With \(k=1\) it degenerates to a binary mutex.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
A semaphore initialised to {{c1::1}} (<code>sem_mutex = Semaphore(1)</code>) acts as a lock: {{c2::<code>lock()</code> is <code>sem_mutex.acquire()</code>}} and {{c2::<code>unlock()</code> is <code>sem_mutex.release()</code>}}. In general the value means: \(1\) is {{c3::unlocked}}, \(0\) is {{c3::locked}}, \(x > 0\) means {{c3::\(x\) threads will be let into the "critical section"}}. |
| Extra |
|
A semaphore with initial value \(k > 1\) is therefore a generalised lock that admits up to \(k\) threads concurrently (a counting semaphore). With \(k=1\) it degenerates to a binary mutex. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Note 57: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: Tb@BJO%9v+
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
In the producer-consumer pattern, thread \(T_0\) computes a value \(X\) and passes it to \(T_1\) which uses \(X\). Synchronisation on \(X\) itself is not needed, because at any point in time only one thread accesses \(X\); what is needed is a synchronised mechanism to pass \(X\) from \(T_0\) to \(T_1\) (typically a queue).
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
In the producer-consumer pattern, thread \(T_0\) computes a value \(X\) and passes it to \(T_1\) which uses \(X\). Synchronisation on \(X\) itself is not needed, because at any point in time only one thread accesses \(X\); what is needed is a synchronised mechanism to pass \(X\) from \(T_0\) to \(T_1\) (typically a queue).
Producer-consumer is a fundamental parallel-programming pattern. Pipelines \(T_0 \to T_1 \to T_2\) generalise it: middle stages are both producer and consumer. Programmable hardware like Intel Stratix 10 (30 billion transistors) is built around exactly this dataflow style.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
In the producer-consumer pattern, thread \(T_0\) computes a value \(X\) and passes it to \(T_1\) which uses \(X\). Synchronisation on \(X\) itself is {{c1::not needed, because at any point in time only one thread accesses \(X\)}}; what is needed is {{c2::a synchronised mechanism to pass \(X\) from \(T_0\) to \(T_1\) (typically a queue)}}. |
| Extra |
|
Producer-consumer is a fundamental parallel-programming pattern. Pipelines \(T_0 \to T_1 \to T_2\) generalise it: middle stages are both producer and consumer. Programmable hardware like Intel Stratix 10 (30 billion transistors) is built around exactly this dataflow style. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
Note 58: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: UvyKN*oVmU
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::12._Lock_and_Condition
A Java Condition (obtained via lock.newCondition()) offers await(): must be called with the lock held; atomically releases the lock and waits until the thread is signalled; on return, the lock is guaranteed to be held again; the thread always needs to re-check the condition (use while, not if). Plus signal() / signalAll(): also called with the lock held, wakes one or all threads waiting on this specific condition.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::12._Lock_and_Condition
A Java Condition (obtained via lock.newCondition()) offers await(): must be called with the lock held; atomically releases the lock and waits until the thread is signalled; on return, the lock is guaranteed to be held again; the thread always needs to re-check the condition (use while, not if). Plus signal() / signalAll(): also called with the lock held, wakes one or all threads waiting on this specific condition.
Crucial difference from wait/notify on intrinsic locks: a single lock can have multiple conditions, so producers and consumers can wait on different ones (notFull, notEmpty) and the right kind of waiter can be woken directly without notifying all.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
A Java <code>Condition</code> (obtained via <code>lock.newCondition()</code>) offers {{c1::<code>await()</code>}}: must be called with the lock held; {{c2::atomically releases the lock and waits until the thread is signalled}}; on return, the lock is {{c3::guaranteed to be held again}}; the thread {{c4::always needs to re-check the condition (use <code>while</code>, not <code>if</code>)}}. Plus <code>signal()</code> / <code>signalAll()</code>: also called with the lock held, wakes one or all threads waiting on this specific condition. |
| Extra |
|
Crucial difference from <code>wait/notify</code> on intrinsic locks: a single lock can have <em>multiple</em> conditions, so producers and consumers can wait on different ones (<code>notFull</code>, <code>notEmpty</code>) and the right kind of waiter can be woken directly without notifying all. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::12._Lock_and_Condition
Note 59: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: ZTD^ST04cP
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
A bounded FIFO queue is implemented as a circular buffer with two indices: in (next free slot) and out (next element to remove), both advanced modulo size. The state of the buffer is determined by these two indices: isEmpty() returns in == out and isFull() returns (in + 1) % size == out.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
A bounded FIFO queue is implemented as a circular buffer with two indices: in (next free slot) and out (next element to remove), both advanced modulo size. The state of the buffer is determined by these two indices: isEmpty() returns in == out and isFull() returns (in + 1) % size == out.
The wrap-around semantics of (i + 1) % size is what makes it "circular": the buffer can be visualised as a ring with in chasing out.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
A bounded FIFO queue is implemented as a {{c1::circular buffer}} with two indices: <code>in</code> (next free slot) and <code>out</code> (next element to remove), both advanced modulo <code>size</code>. The state of the buffer is determined by these two indices: <code>isEmpty()</code> returns {{c2::<code>in == out</code>}} and <code>isFull()</code> returns {{c2::<code>(in + 1) % size == out</code>}}. |
| Extra |
|
The wrap-around semantics of <code>(i + 1) % size</code> is what makes it "circular": the buffer can be visualised as a ring with <code>in</code> chasing <code>out</code>. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
Note 60: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: ^q02oC6MbX
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::12._Lock_and_Condition
Producer-consumer with
ReentrantLock + two conditions
notFull and
notEmpty:
void enqueue(long x) {
lock.lock();
while (isFull()) notFull.await();
doEnqueue(x);
notEmpty.signal();
lock.unlock();
}Why this is cleaner than
synchronized +
wait /
notifyAll:
with two conditions, the producer signals only consumers on notEmpty, not all waiters on the object's single intrinsic queue, so
signal() instead of signalAll() suffices in this pattern (every waiter on notEmpty is a consumer, every waiter on notFull is a producer, no risk of waking the wrong kind of thread).
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::12._Lock_and_Condition
Producer-consumer with
ReentrantLock + two conditions
notFull and
notEmpty:
void enqueue(long x) {
lock.lock();
while (isFull()) notFull.await();
doEnqueue(x);
notEmpty.signal();
lock.unlock();
}Why this is cleaner than
synchronized +
wait /
notifyAll:
with two conditions, the producer signals only consumers on notEmpty, not all waiters on the object's single intrinsic queue, so
signal() instead of signalAll() suffices in this pattern (every waiter on notEmpty is a consumer, every waiter on notFull is a producer, no risk of waking the wrong kind of thread).
With a single intrinsic monitor and one queue (mixing producers and consumers), notify() could wake a producer when the queue is full, which would just go back to wait: hence notifyAll is required there.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Producer-consumer with <code>ReentrantLock</code> + two conditions <code>notFull</code> and <code>notEmpty</code>: <pre>void enqueue(long x) {
lock.lock();
while (isFull()) notFull.await();
doEnqueue(x);
notEmpty.signal();
lock.unlock();
}</pre>Why this is cleaner than <code>synchronized</code> + <code>wait</code> / <code>notifyAll</code>: {{c1::with two conditions, the producer signals only consumers on <code>notEmpty</code>, not all waiters on the object's single intrinsic queue}}, so {{c2::<code>signal()</code> instead of <code>signalAll()</code> suffices in this pattern (every waiter on <code>notEmpty</code> is a consumer, every waiter on <code>notFull</code> is a producer, no risk of waking the wrong kind of thread)}}. |
| Extra |
|
With a single intrinsic monitor and one queue (mixing producers and consumers), <code>notify()</code> could wake a producer when the queue is full, which would just go back to <code>wait</code>: hence <code>notifyAll</code> is required there. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::12._Lock_and_Condition
Note 61: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: _19oq0$uNl
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Correct rendezvous implementation with
P_Arrived = Q_Arrived = 0:
| P | Q |
|---|
release(P_Arrived)
acquire(Q_Arrived) | release(Q_Arrived)
acquire(P_Arrived) |
Rule:
signal first ("I am here"), then wait ("are you here too?"). No deadlock is possible because the own
release is already executed before waiting on the other one.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Correct rendezvous implementation with
P_Arrived = Q_Arrived = 0:
| P | Q |
|---|
release(P_Arrived)
acquire(Q_Arrived) | release(Q_Arrived)
acquire(P_Arrived) |
Rule:
signal first ("I am here"), then wait ("are you here too?"). No deadlock is possible because the own
release is already executed before waiting on the other one.
Whether P or Q arrives first does not matter: the earlier one waits, the later one triggers both releases before its acquire. Both pass the rendezvous as soon as the second thread arrives.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Correct rendezvous implementation with <code>P_Arrived = Q_Arrived = 0</code>: <table border="1" cellpadding="4"><tr><th>P</th><th>Q</th></tr><tr><td>{{c1::<code>release(P_Arrived)</code><br><code>acquire(Q_Arrived)</code>}}</td><td>{{c1::<code>release(Q_Arrived)</code><br><code>acquire(P_Arrived)</code>}}</td></tr></table>Rule: {{c2::signal first ("I am here"), then wait ("are you here too?")}}. No deadlock is possible because the own <code>release</code> is already executed before waiting on the other one. |
| Extra |
|
Whether P or Q arrives first does not matter: the earlier one waits, the later one triggers both releases before its acquire. Both pass the rendezvous as soon as the second thread arrives. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Note 62: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: dGibG|?+t-
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
A monitor adds, on top of mutual exclusion, the following condition mechanism: if a condition does not hold, release the monitor lock, wait for the condition to become true, and use a signalling mechanism (rather than a busy-loop) to be woken when it does. Internally, a monitor maintains two queues: a waiting entry queue (threads trying to acquire the monitor) and a waiting condition queue (threads inside the monitor that have called wait).
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
A monitor adds, on top of mutual exclusion, the following condition mechanism: if a condition does not hold, release the monitor lock, wait for the condition to become true, and use a signalling mechanism (rather than a busy-loop) to be woken when it does. Internally, a monitor maintains two queues: a waiting entry queue (threads trying to acquire the monitor) and a waiting condition queue (threads inside the monitor that have called wait).
The two queues are conceptually distinct: a thread that is signalled is moved from the condition queue back to the entry queue (under signal-and-continue), it does not get the lock immediately.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
A monitor adds, on top of mutual exclusion, the following condition mechanism: if a condition does not hold, {{c1::release the monitor lock}}, {{c2::wait for the condition to become true}}, and use {{c3::a signalling mechanism (rather than a busy-loop) to be woken when it does}}. Internally, a monitor maintains two queues: {{c4::a <em>waiting entry</em> queue (threads trying to acquire the monitor)}} and {{c4::a <em>waiting condition</em> queue (threads inside the monitor that have called wait)}}. |
| Extra |
|
The two queues are conceptually distinct: a thread that is signalled is moved from the condition queue back to the entry queue (under signal-and-continue), it does not get the lock immediately. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
Note 63: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: fuGa|7fW/T
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
A monitor-based semaphore with
synchronized acquire() { if (number <= 0) wait(); number--; }
synchronized release() { number++; if (number > 0) notify(); }is
broken under signal-and-continue semantics (which is what Java uses). Concrete scenario with threads P, Q, R:
(1) P entered earlier and decremented number to 0; (2) Q sees 0 and goes to the condition queue; (3) P calls release(): increments number to 1, calls notify() which moves Q to the entry queue, then P exits the monitor; (4) R now calls acquire(), finds number = 1 > 0, decrements to 0 and proceeds; (5) Q, when it finally acquires the lock, decrements number to \(-1\), an inconsistency. The cure:
replace if with while (re-check the condition after waking).
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
A monitor-based semaphore with
synchronized acquire() { if (number <= 0) wait(); number--; }
synchronized release() { number++; if (number > 0) notify(); }is
broken under signal-and-continue semantics (which is what Java uses). Concrete scenario with threads P, Q, R:
(1) P entered earlier and decremented number to 0; (2) Q sees 0 and goes to the condition queue; (3) P calls release(): increments number to 1, calls notify() which moves Q to the entry queue, then P exits the monitor; (4) R now calls acquire(), finds number = 1 > 0, decrements to 0 and proceeds; (5) Q, when it finally acquires the lock, decrements number to \(-1\), an inconsistency. The cure:
replace if with while (re-check the condition after waking).
Under signal-and-wait the lock would have been handed straight to Q, blocking R, and if would have sufficed. Java's signal-and-continue is what forces the while idiom, together with the possibility of spurious wakeups.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
A monitor-based semaphore with <pre>synchronized acquire() { if (number <= 0) wait(); number--; }
synchronized release() { number++; if (number > 0) notify(); }</pre>is {{c1::broken under signal-and-continue semantics (which is what Java uses)}}. Concrete scenario with threads P, Q, R: {{c2::(1) P entered earlier and decremented <code>number</code> to 0; (2) Q sees 0 and goes to the condition queue; (3) P calls <code>release()</code>: increments <code>number</code> to 1, calls <code>notify()</code> which moves Q to the entry queue, then P exits the monitor; (4) R now calls <code>acquire()</code>, finds <code>number = 1 > 0</code>, decrements to 0 and proceeds; (5) Q, when it finally acquires the lock, decrements <code>number</code> to \(-1\), an inconsistency}}. The cure: {{c3::replace <code>if</code> with <code>while</code> (re-check the condition after waking)}}. |
| Extra |
|
Under signal-and-wait the lock would have been handed straight to Q, blocking R, and <code>if</code> would have sufficed. Java's signal-and-continue is what forces the <code>while</code> idiom, together with the possibility of spurious wakeups. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
Note 64: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: g-H0<*^eyz
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Locks alone are insufficient because they only enforce atomicity via mutual exclusion, but provide no means for threads to communicate about state changes, and they provide no order: if threads A and B both lock object X, it is undetermined who comes first. Canonical example where this hurts: producer / consumer queues.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Locks alone are insufficient because they only enforce atomicity via mutual exclusion, but provide no means for threads to communicate about state changes, and they provide no order: if threads A and B both lock object X, it is undetermined who comes first. Canonical example where this hurts: producer / consumer queues.
Semaphores and higher-level primitives fill exactly this gap: they let one thread signal another that something has happened, and thus impose a partial order on executions.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Locks alone are insufficient because {{c1::they only enforce atomicity via mutual exclusion, but provide no means for threads to communicate about state changes}}, and {{c2::they provide no order: if threads A and B both lock object X, it is undetermined who comes first}}. Canonical example where this hurts: {{c3::producer / consumer queues}}. |
| Extra |
|
Semaphores and higher-level primitives fill exactly this gap: they let one thread signal another that something has happened, and thus impose a partial order on executions. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Note 65: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: h#Z>rJrnYr
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
In a circular-buffer FIFO, one slot is left unusable on purpose so that isFull() is (in + 1) % size == out rather than using a separate counter variable. The benefit of avoiding a counter: in is only written by the producer and out only by the consumer, so for the single-producer single-consumer case the two indices need no mutual exclusion against each other.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
In a circular-buffer FIFO, one slot is left unusable on purpose so that isFull() is (in + 1) % size == out rather than using a separate counter variable. The benefit of avoiding a counter: in is only written by the producer and out only by the consumer, so for the single-producer single-consumer case the two indices need no mutual exclusion against each other.
A counter count would be incremented by the producer and decremented by the consumer, a write-write conflict that forces synchronisation even on the fast path. Sacrificing one slot of capacity buys a much cleaner concurrency story.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
In a circular-buffer FIFO, one slot is left unusable on purpose so that <code>isFull()</code> is <code>(in + 1) % size == out</code> rather than using a separate counter variable. The benefit of avoiding a counter: {{c1::<code>in</code> is only written by the producer and <code>out</code> only by the consumer, so for the single-producer single-consumer case the two indices need no mutual exclusion against each other}}. |
| Extra |
|
A counter <code>count</code> would be incremented by the producer and decremented by the consumer, a write-write conflict that forces synchronisation even on the fast path. Sacrificing one slot of capacity buys a much cleaner concurrency story. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
Note 66: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: iM|cWW?YzD
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Scaling a dot product to 1 million entries on 10 000 threads is impractical with semaphores or locks. It calls for a higher-level abstraction supporting threads in bulk mode (all moving in lock-step). The corresponding programming model is Bulk-Synchronous Parallel (BSP).
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Scaling a dot product to 1 million entries on 10 000 threads is impractical with semaphores or locks. It calls for a higher-level abstraction supporting threads in bulk mode (all moving in lock-step). The corresponding programming model is Bulk-Synchronous Parallel (BSP).
The full BSP model (Valiant, 1990) is more general and supports distributed memory: computation proceeds in supersteps consisting of local computation, communication, and a global barrier. In shared-memory code the barrier is the central building block.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Scaling a dot product to 1 million entries on 10 000 threads is impractical with semaphores or locks. It calls for a higher-level abstraction supporting {{c1::threads in bulk mode}} (all moving in lock-step). The corresponding programming model is {{c2::Bulk-Synchronous Parallel (BSP)}}. |
| Extra |
|
The full BSP model (Valiant, 1990) is more general and supports distributed memory: computation proceeds in supersteps consisting of local computation, communication, and a global barrier. In shared-memory code the barrier is the central building block. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Note 67: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: kU$/VTuynM
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::7._Deadlock_Avoidance
The historic Java StringBuffer.append(StringBuffer sb) (synchronized append(...){ int len = sb.length(); ... sb.getChars(0, len, value, count); }) has two problems: the lock on sb is not held between sb.length() and sb.getChars(...), so sb can grow or shrink in between (a shrinking sb definitely breaks append) and deadlock potential on crossing calls x.append(y) and y.append(x) on two threads, analogous to the bank-account transfer example.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::7._Deadlock_Avoidance
The historic Java StringBuffer.append(StringBuffer sb) (synchronized append(...){ int len = sb.length(); ... sb.getChars(0, len, value, count); }) has two problems: the lock on sb is not held between sb.length() and sb.getChars(...), so sb can grow or shrink in between (a shrinking sb definitely breaks append) and deadlock potential on crossing calls x.append(y) and y.append(x) on two threads, analogous to the bank-account transfer example.
Neither problem is easy to fix without overhead: you do not want a unique id on every StringBuffer, nor a single global lock for all of them. The Java library initially fixed neither (only changed the javadoc) and later split the API into StringBuffer (claimed synchronized) and StringBuilder (not synchronized), leaving clients to avoid such situations with their own protocols.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
The historic Java <code>StringBuffer.append(StringBuffer sb)</code> (<code>synchronized append(...){ int len = sb.length(); ... sb.getChars(0, len, value, count); }</code>) has two problems: {{c1::the lock on <code>sb</code> is not held between <code>sb.length()</code> and <code>sb.getChars(...)</code>, so <code>sb</code> can grow or shrink in between (a shrinking <code>sb</code> definitely breaks <code>append</code>)}} and {{c2::deadlock potential on crossing calls <code>x.append(y)</code> and <code>y.append(x)</code> on two threads, analogous to the bank-account transfer example}}. |
| Extra |
|
Neither problem is easy to fix without overhead: you do not want a unique id on every <code>StringBuffer</code>, nor a single global lock for all of them. The Java library initially fixed neither (only changed the javadoc) and later split the API into <code>StringBuffer</code> (claimed synchronized) and <code>StringBuilder</code> (not synchronized), leaving clients to avoid such situations with their own protocols. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::7._Deadlock_Avoidance
Note 68: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: ntkbNkNy_m
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
Two main monitor signalling semantics: signal and wait: the signalling process exits the monitor (goes to the waiting-entry queue) and passes the monitor lock directly to the signalled process. signal and continue: the signalling process continues running and merely moves the signalled process to the waiting-entry queue, where it must reacquire the lock like anyone else.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
Two main monitor signalling semantics: signal and wait: the signalling process exits the monitor (goes to the waiting-entry queue) and passes the monitor lock directly to the signalled process. signal and continue: the signalling process continues running and merely moves the signalled process to the waiting-entry queue, where it must reacquire the lock like anyone else.
Other variants exist (signal-and-exit, signal-and-urgent-wait, ...). Java uses signal-and-continue, which has important consequences for how condition checks must be coded (always while, never if).
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Two main monitor signalling semantics: {{c1::<em>signal and wait</em>}}: {{c2::the signalling process exits the monitor (goes to the waiting-entry queue) and passes the monitor lock directly to the signalled process}}. {{c3::<em>signal and continue</em>}}: {{c4::the signalling process continues running and merely moves the signalled process to the waiting-entry queue, where it must reacquire the lock like anyone else}}. |
| Extra |
|
Other variants exist (signal-and-exit, signal-and-urgent-wait, ...). Java uses <em>signal-and-continue</em>, which has important consequences for how condition checks must be coded (always <code>while</code>, never <code>if</code>). |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::11._Monitors
Note 69: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: sCYbBLISvG
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
A semaphore is an integer-valued abstract data type S with some initial value \(s \geq 0\) and two atomic operations: acquire(S): wait until S > 0, then dec(S) and release(S): inc(S).
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
A semaphore is an integer-valued abstract data type S with some initial value \(s \geq 0\) and two atomic operations: acquire(S): wait until S > 0, then dec(S) and release(S): inc(S).
Introduced by Edsger W. Dijkstra (1965); originally called P (probeeren) and V (vrijgeven), often also wait and signal. Unlike a lock, a semaphore has no owner: the thread that calls release need not be the one that called acquire.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
A {{c1::semaphore}} is an integer-valued abstract data type <code>S</code> with some initial value \(s \geq 0\) and two atomic operations: {{c2::<code>acquire(S)</code>: wait until <code>S > 0</code>, then <code>dec(S)</code>}} and {{c2::<code>release(S)</code>: <code>inc(S)</code>}}. |
| Extra |
|
Introduced by Edsger W. Dijkstra (1965); originally called <code>P</code> (probeeren) and <code>V</code> (vrijgeven), often also <em>wait</em> and <em>signal</em>. Unlike a lock, a semaphore has no owner: the thread that calls <code>release</code> need not be the one that called <code>acquire</code>. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Note 70: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: x$osz_e?7R
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Wrong rendezvous implementation with
P_Arrived = Q_Arrived = 0:
| P | Q |
|---|
acquire(Q_Arrived)
release(P_Arrived) | acquire(P_Arrived)
release(Q_Arrived) |
Problem:
deadlock, because
both threads acquire before anyone has released: P needs Q_Arrived (held by Q), Q needs P_Arrived (held by P): a circular wait.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Wrong rendezvous implementation with
P_Arrived = Q_Arrived = 0:
| P | Q |
|---|
acquire(Q_Arrived)
release(P_Arrived) | acquire(P_Arrived)
release(Q_Arrived) |
Problem:
deadlock, because
both threads acquire before anyone has released: P needs Q_Arrived (held by Q), Q needs P_Arrived (held by P): a circular wait.
Lesson: in a rendezvous, always signal first, then wait. Otherwise a classic hold-and-wait cycle forms because neither thread ever reaches its release.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Wrong rendezvous implementation with <code>P_Arrived = Q_Arrived = 0</code>: <table border="1" cellpadding="4"><tr><th>P</th><th>Q</th></tr><tr><td><code>acquire(Q_Arrived)</code><br><code>release(P_Arrived)</code></td><td><code>acquire(P_Arrived)</code><br><code>release(Q_Arrived)</code></td></tr></table>Problem: {{c1::deadlock}}, because {{c2::both threads acquire before anyone has released: <code>P</code> needs <code>Q_Arrived</code> (held by Q), <code>Q</code> needs <code>P_Arrived</code> (held by P): a circular wait}}. |
| Extra |
|
Lesson: in a rendezvous, always <em>signal first, then wait</em>. Otherwise a classic hold-and-wait cycle forms because neither thread ever reaches its <code>release</code>. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::8._Semaphores
Note 71: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: xHZU%tugzy
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
Producer-consumer with three semaphores nonEmpty = Semaphore(0), nonFull = Semaphore(size), manipulation = Semaphore(1): the order manipulation.acquire(); nonFull.acquire(); in enqueue (and analogously manipulation before nonEmpty in dequeue) deadlocks: a producer holding manipulation on a full queue waits on nonFull, while the consumer needs manipulation to remove an item: a circular wait between manipulation and nonFull / nonEmpty. Fix: acquire the resource semaphore before the manipulation mutex (nonFull.acquire(); manipulation.acquire();), so the resource wait happens outside the critical section.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
Producer-consumer with three semaphores nonEmpty = Semaphore(0), nonFull = Semaphore(size), manipulation = Semaphore(1): the order manipulation.acquire(); nonFull.acquire(); in enqueue (and analogously manipulation before nonEmpty in dequeue) deadlocks: a producer holding manipulation on a full queue waits on nonFull, while the consumer needs manipulation to remove an item: a circular wait between manipulation and nonFull / nonEmpty. Fix: acquire the resource semaphore before the manipulation mutex (nonFull.acquire(); manipulation.acquire();), so the resource wait happens outside the critical section.
General rule when nesting semaphores: acquire the one you might block on first, the one you merely need for exclusion second. This breaks the hold-and-wait cycle.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Producer-consumer with three semaphores <code>nonEmpty = Semaphore(0)</code>, <code>nonFull = Semaphore(size)</code>, <code>manipulation = Semaphore(1)</code>: the order <code>manipulation.acquire(); nonFull.acquire();</code> in <code>enqueue</code> (and analogously <code>manipulation</code> before <code>nonEmpty</code> in <code>dequeue</code>) {{c1::deadlocks}}: a producer holding <code>manipulation</code> on a full queue waits on <code>nonFull</code>, while the consumer needs <code>manipulation</code> to remove an item: {{c2::a circular wait between <code>manipulation</code> and <code>nonFull</code> / <code>nonEmpty</code>}}. Fix: {{c3::acquire the resource semaphore <em>before</em> the <code>manipulation</code> mutex (<code>nonFull.acquire(); manipulation.acquire();</code>)}}, so the resource wait happens outside the critical section. |
| Extra |
|
General rule when nesting semaphores: acquire the one you might block on first, the one you merely need for exclusion second. This breaks the hold-and-wait cycle. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::10._Producer-Consumer
Note 72: ETH::2. Semester::PProg
Deck: ETH::2. Semester::PProg
Note Type: Horvath Cloze
GUID: y4X/i|x>Tz
added
Previous
Note did not exist
New Note
Front
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Wrong barrier implementation with semaphore barrier = 0 and shared variable count = 0: each thread does count++; if (count == n) release(barrier); acquire(barrier);. Problems: race condition on count++ (no mutex) and deadlock, because release is called only once but \(n\) threads acquire: after the first acquire the semaphore is back to 0, so all others wait forever.
Back
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers
Wrong barrier implementation with semaphore barrier = 0 and shared variable count = 0: each thread does count++; if (count == n) release(barrier); acquire(barrier);. Problems: race condition on count++ (no mutex) and deadlock, because release is called only once but \(n\) threads acquire: after the first acquire the semaphore is back to 0, so all others wait forever.
Violated invariants: "count gives the number of processes that have passed the barrier" and "once all processes have reached the barrier, all waiting processes can continue". Both must be fixed separately: the race with a mutex, the deadlock with a turnstile.
Field-by-field Comparison
| Field |
Before |
After |
| Text |
|
Wrong barrier implementation with semaphore <code>barrier = 0</code> and shared variable <code>count = 0</code>: each thread does <code>count++; if (count == n) release(barrier); acquire(barrier);</code>. Problems: {{c1::race condition on <code>count++</code> (no mutex)}} and {{c2::deadlock, because <code>release</code> is called only once but \(n\) threads <code>acquire</code>: after the first <code>acquire</code> the semaphore is back to 0, so all others wait forever}}. |
| Extra |
|
Violated invariants: "count gives the number of processes that have passed the barrier" and "once all processes have reached the barrier, all waiting processes can continue". Both must be fixed separately: the race with a mutex, the deadlock with a turnstile. |
Tags:
ETH::2._Semester::PProg::12._Shared_Memory_Concurrency::9._Barriers