Dydaktyka
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Help
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Ćwiczenia 2, grupa śr. 16-18, 26 października 2022 ###### tags: `PRW22` `ćwiczenia` `pwit` ## Deklaracje Gotowość rozwiązania zadania należy wyrazić poprzez postawienie X w odpowiedniej kolumnie! Jeśli pożądasz zreferować dane zadanie (co najwyżej jedno!) w trakcie dyskusji oznacz je znakiem ==X== na żółtym tle. **UWAGA: Tabelkę wolno edytować tylko wtedy, gdy jest na zielonym tle!** :::danger | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | | ----------------------:| ----- | --- | --- | --- | --- | --- | --- | --- | Daniel Boguszewski | x | x | x | x | x | | | | Marcin Dąbrowski | | | | | | | | | Jakub Gałecki | | | | | | | | | Kamila Goszcz | X | X | | X | | X | X | | Wiktor Hamberger | X | X | ==X== | | | | | | Jan Jankowicz | X | X | X | | | | | | Mikołaj Jaszcza | x | x | x | x | | x | x | | Zuzanna Kania | | X | X | | | | | | Wiktoria Kuna | | | | | | | | | Patryk Mazur | X | X | X | | | | | | Hubert Obrzut | X | X | X | X | X | X | X |==X==| Magdalena Rzepka | ==X== | X | X | X | X | X | X | X | Joanna Stachowicz | X | | X | | | | | | Rafał Starypan | | | | | | | | | Maria Szlasa | X | X | X | X | X | X | ==X== | X | Daniel Wiczołek | X | X | X | X | X | X | X | | ::: :::info **Uwaga:** Po rozwiązaniu zadania należy zmienić kolor nagłówka na zielony. ::: ## Zadanie 1 :::success Autor: Magdalena Rzepka ::: ![](https://i.imgur.com/trJg57x.png =700x) **a)wzajemne wykluczanie - spełnia** Załóżmy, że mamy dwa wątki o id 1 i 2, które mogą przejść razem do sekcji krytycznej. **Wiemy, że:** W~1~(turn = 1) -> R~1~(busy == false) -> W~1~(busy == true) -> R~1~(turn == 1) (analogicznie dla wątku 2): **Z tego wynika, że:** R~1~(turn == 1) -> W~2~(turn = 2) -> R~2~(turn == 2) -> W~1~(turn = 1) -> R~1~(turn == 1) R~1~ -> R~1~ co jest sprzecznością. Poprawne sprawdzenie czy jest nasza kolej musi nastąpić zanim inny wątek nam go nadpisze. Nadpisanie wątka musi nastąpić przed sprawdzeniem czy ciągle jest nadpisany. Z kolei sprawdzenie czy ciągle jest nasza kolej musi nastąpić przed tym jak inny wątek nam go nadpisze. A to musi być przed sprawdzeniem czy to nasza kolej. Zrobiliśmy pętelkę i doszliśmy do sprzeczności. Musi zachodzić wzajemne wykluczanie. **b)niezagłodzenie - nie spełnia** Wystarczy pokazać na jednym przykładzie, że może dojść do zagłodzenia. W~1~(turn = 1) R~1~(busy != true) W~1~(busy = true) i wychodzi z pętli W~2~(turn = 2) R~2~(busy = true) - zawiesza się W~1~(busy = false) - robi unlock() Wątek 1 od razu wchodzi do funkcji lock(), ustawia turn = 1 i idze dalej zablokować busy = true. Wątek 2 jest wolniejszy i zanim się zorientował znowu został zamknięty w pętli. Wątek 2 jest wątkiem głodzonym. **c)niezakleszczenie - nie spełnia** Wątek 1 ustawia turn = 1 i busy = true. Wątek 2 ustawia turn = 2 i zapętla się bo busy = true. Wątek 1 sprawdza while ale turn != 1. Wraca więc i ustawia turn = 1. Wątek 1 również się zapętla bo busy = true. ## Zadanie 2 :::success Autor: Patryk Mazur ::: ![](https://i.imgur.com/Shkvmk3.png) ### Niezakleszczenie Wiemy, że `lock()` w algorytmie Petersona nie może powodować zakleszczenia, ponieważ w tej wersji `unlock()` wątek, który wyszedł z sekcji krytycznej nadal obniża swoją flagę. Oba wątki, które przejdą do `unlock()`, opuszczają swoją flagę, przez co niemożliwe jest zakleszczenie w tym while'u ### Niezagłodzenie W tej wersji algorytmu moze dojść do zagłodzenia Watek `A` może zablokować się w `unlock()` i przesypiać momenty gdy `flag[B]=false`. Wątek `B` będzie mógł wchodzić do sekcji krytycznej z tytułu `flag[A]=false`. ## Zadanie 3 :::success Autor: Wiktor Hamberger ::: :::info **Zadanie 3.** Przypomnij, co to znaczy że algorytm ma własność r-ograniczonego czekania (ang. r-Bounded Waiting). Czym są sekcja wejściowa (ang. doorway section) i sekcja oczekiwania (ang. waiting section) w algorytmie Petersena? Pokaż, że ten algorytm ma własność 0-ograniczonego czekania, tzn, że jest FCFS (First Come First Served). ::: 1. Przypomnij, co to znaczy że algorytm ma własność r-ograniczonego czekania (ang. r-Bounded Waiting). ![](https://i.imgur.com/NA3sKKO.png) ![](https://i.imgur.com/ICH3p6X.png) 2. Czym są sekcja wejściowa (ang. doorway section) [zielony] i sekcja oczekiwania (ang. waiting section) [czerwony] w algorytmie Petersena? ![](https://i.imgur.com/85PDYcL.png) 3. Pokaż, że ten algorytm ma własność 0-ograniczonego czekania, tzn, że jest FCFS (First Come First Served). Należy udowodnić że: $$ D^k_A \to D^j_B \Rightarrow CS^k_A \to CS^j_B $$ rozpiszmy lewą stronę implikacji: $$ write_A(flag[A]=true)\to write_A(victim=A) \to^{1.} write_B(flag[B]=true) \to^{2.} write_B(victim=B)^{3.} $$ Dla warunku w $W_A$ i $W_B$ istnieją 3 momenty w czasie, w takcie których wątek/wątki mogą się chcieć dostać do $CS$ oznaczone powyżej jako $1.$, $2.$ i $3.$. Rozpiszmy sobie możliwości stnanów sarunków w sekcjach wejściowych: 1. $flag[B]==false \Rightarrow CS_A \to CS_B$ 2. $flag[B]==true, victim==A \Rightarrow nic\quad się\quad nie\quad dzieje$ 3. $flag[B]==true, flag[A]==true, victim==B \Rightarrow CS_A \to CS_B$ C.b.d.U. ## Zadanie 4 :::success Autor: Daniel Boguszewski ::: ![](https://i.imgur.com/WIdPDWM.png) ![](https://i.imgur.com/JT5rk3K.jpg) ![](https://i.imgur.com/OxWcxcT.png) Algorytm można zwizualizować jako pełne drzewo binarne o n/2 liściach, przy czym od każdego z liści wychodzą dodatkowe dwa 'węzły', będące wątkami, na których wykonuje się program (razem n wątków). Aby dany wątek przeszedł do sekcji krytycznej programu, musi przejść całą drogę od liścia do korzenia tego drzewa, przy czym każdy z węzłów jest zamkiem działającym w algorytmie Petersona. Można powiedzieć, że w każdym z węzłów znajduje się sekcja krytyczna, do której o dostęp spierają się jego dzieci. Faktyczna sekcja krytyczna programu znajduje się w korzeniu, reszta węzłów służy jako kolejka dla wątków, które próbują się dostać do sekcji krytycznej. Aby się do niej dostać, wątek musi zostać dopuszczony do każdego węzła na swojej ścieżce. Wątki traktowane są jako 0 lub 1, w zależności od tego, czy są lewym czy prawym dzieckiem danego węzła. Ma to następujące konsekwencje: Algorytm posiada własność wzajemnego wykluczania: Załóżmy, że Ai wykonuje SC, zatem zamek na każdym węźle ścieżki przez którą przechodził przepuścił Ai. Oznacza to, że flag[i] = true i żaden inny wątek nie przejdzie przez jego sekcje oczekiwania (flag[0] oraz flag[1] będą równe true). Tym samym sekcję krytyczną wykonuje maksymalnie jeden wątek. Algorytm posiada własność niezagłodzenia: Załóżmy, że Ai próbuje się dostać do SC, ale tę wykonuje aktualnie inny wątek (flag[i] = flag[j] = true, victim = i). Oznacza to, że na ścieżce do SC zostanie zatrzymany na jednym z węzłów. Ten węzeł zostanie wreszcie zwolniony, wówczas flag[j] = false. Jeśli wątek wznowi działanie, nim do sekcji dostępu dotrze inny wątek, zostanie przepuszczony węzeł wyżej. W innym wypadku pewien wątek Aj zastąpi wartości na flag[j] = true oraz victim = j. Ze względu na wartość zmiennej victim, nie zostanie dopuszczony dalej przed wątkiem Ai. Wobec tego wątek Ai będzie posuwać się po pewnym skończonym czasie coraz wyżej, aż wreszcie dotrze do SC. Algorytym posiada własność niezakleszczenia: W dowolnym z węzłów, jeśli 2 wątki domagają się przejścia do SC, uda się to tylko jednemu. Załóżmy, że wątek Ai oraz Aj próbują przejść przez zamek. Wówczas w czasie wykonywaniu sekcji dostępu oba z nich będą musiały nadać wartość zmiennej victim, ta jednak może posiadać tylko jedną wartość. Niedopuszczony zostanie wątek, który nie przydzielił victim swojej wartości, drugi wątek przejdzie dalej, a przepływ pozostanie niezaburzony. Ponieważ na drodze jest skończona liczba wątków, w końcu dotrze do sekcji krytycznej. ## Zadanie 5 :::success Autor: Daniel Wiczołek ::: ![](https://i.imgur.com/1Jspl3L.png) 1. ![](https://i.imgur.com/yuM4Xya.png) ![](https://i.imgur.com/nttVpUx.png) Nie ma ograniczenia bo unlock moze byc wolny i to główne prawe poddrzewo może być wielokrotnie wykorzystane. (bez strat na ogólności patrzę na skrajnie lewe) ![](https://i.imgur.com/MZJHjDh.png) L1 - wątek w lewym liściu L2 - drugi z lewego P1, P2 - analogicznie prawy L1: próbuje wejść do CS L2: robi unlock w root ale powoli P2: nie probuje wejsc do CS P1: wchodzi $n$ razy wniosek: P1 może wejść dowolną liczbę razy zanim L2 oblokuje liść z L1 2. Do każdego dochodzą 2 więc wystarczy pamiętać, z którego poddrzewa przychodzimy ## Zadanie 6 :::success Autor: Mikołaj Jaszcza ::: W dobrze zaprojektowanym programie wielowątkowym rywalizacja o zamki powinna być niewielka. Najbardziej praktyczną miarą wydajności algorytmu implementującego zamek jest więc liczba kroków potrzebna do zajęcia wolnego zamku, jeśli tylko jeden wątek się o to ubiega. Poniższy kod jest propozycją uniwersalnego wrappera, który ma przekształcić dowolny zamek na zamek wykonujący tylko stałą liczbę kroków w opisanym przypadku. Czy ten algorytm spełnia warunek a) wzajemnego wykluczania, b) niezagłodzenia, c) niezakleszczenia? Załóż, że oryginalny zamek spełnia te warunki. ![](https://i.imgur.com/C1ieRft.png) a) **wzajemne wykluczenie** **NIE** Rozważmy sytuację dla 2 wątków. Niech oba wejdą do linijki $$while (y != -1) {} $$ w tym samym momencie. Zauważmy, że wtedy zmienna x ma nadaną jakąś wartość inną niż -1 (bo oba wątki przeszły przez linijkę $$ x = i; $$, a jest to jedyna linijka zmieniająca początkową wartość zmiennej x (bo rozważamy aktualnie tylko lock, ponieważ interesuje nas nielegalne wejście do sekcji krytycznej)). Zatem (BSO) niech x = 0. Wtedy jeden wątek spełni warunek (x != i) i wejdzie do funkcji lock.lock(), a drugi wejdzie bezpośrednio do sekcji krytycznej. Zatem oba jednocześnie mogą znaleźć się w sekcji krytycznej. b) **niezagłodzenie** **NIE** Własność również nie jest spełniona. Niech jeden z dwóch wątków wejdzie do linijki $$ while (y != -1) {} $$ i będzie działał w sposób bardzo wolny. Wtedy drugi wątek może wchodzić i wychodzić nieprzerwanie do sekcji krytycznej. Tj mamy kolejność: -> wątek 1 wywołuje lock -> wątek 1 wchodzi do sekcji krytycznej -> wątek 2 wywołuje lock -> wątek 2 zatrzymuje się w linijce while (y != -1) {} -> wątkowi 2 odebrany zostaje procesor -> wątek 1 wychodzi z sekcji krytycznej i ustawia y := -1 W dalszej części: -> wątek 1 wywołuje lock -> wątek 1 wchodzi do sekcji krytycznej -> wątek 2 dostaje z powrotem procesor, ale nie może wejść do sekcji krytycznej -> wątek 2 czeka, i zostaje mu odebrany procesor -> wątek 1 wychodzi -> powyższe kroki można powtarzać nieskończenie wiele razy, więc wątek 2 może zostać zagłodzony c) **niezakleszczenie** **TAK** Nie wprost. Jeżeli zaszłoby zakleszczenie, to wątki musiałyby się zakleszczyć w 'lock' (oba wątku musiałyby być w 'lock', bo 'unlock' nie zależy od żadnej współdzielonej zmiennej). Zauważmy również, że zakleszczenie musiałoby nastąpić w linijce while (y != -1) {}, bo oprócz tego jedyne miejsce gdzie korzystamy ze współdzielonych zmiennych to 'lock.lock()', ale o tej funkcji wiemy, że nie może zostać zakleszczona, bo wszystkie współdzielone zmienne są dostępne tylko wewnątrz niej. Tzn - nie ingerujemy bezpośrednio w ciele FastPath.lock w ich wartości, czyli zależności między nimi zawsze są poprawne, bo wiemy, że klasyczny 'lock' działa. Jednak jeśli zakleszczenie nastąpiło w linijce while (y != -1) {} to wartość y (różna od -1) musiała zostać ustawiona przez pewien wątek który aktualnie jest w sekcji krytycznej w linijce y = i. Ale wtedy nie mielibyśmy do czynienia z zakleszczeniem, bo po jego wyjściu z sekcji krytycznej wartość y będzie równa -1, więc kolejny wątek (lub wątki) będą miały dostęp do sekcji krytycznej. CKD ## Zadanie 7 :::success Autor: Kamila Goszcz ::: ![](https://i.imgur.com/rzzFazx.png) **a) Co najwyżej jeden wątek może zwrócić STOP** Załóżmy, że jakieś 2 lub więcej wątków się przebiło przez ```c=java if(goRight) return RIGHT; ``` (Gdyby się przebił tylko jeden, to pozostałe zwróciłyby RIGHT, więc aby miały jakąkolwiek szansę coś innego zwrócić niż RIGHT musiały przejść przez tego ifa) i są na etapie: ```c=java goRight = true; if(last == i) return STOP; ``` last jest wspólne i może mieć tylko jedną wartość, zatem tylko jeden wątek zwróci STOP **b) co najwyżej n-1 wątków otrzyma wartość DOWN** Spróbujmy to zepsuć. Niech n wątków się przebije przez ifa i będzie na tym etapie: ```c=java goRight = true; if(last == i) return STOP; else return DOWN; ``` wiemy, że last wskazuje na któreś i, zatem przynajmniej jeden wątek wejdzie w `return STOP` **c) Co najwyżej n-1 wątków otrzyma wartość RIGHT** Aby jakis wątek wszedł w ifa ```c=java if(goRight) return RIGHT; goRight = true; ``` to pierwsze goRight musi być równe true. Jednak, aby ustawić goRight na true, przynajmniej jeden wątek musiał nie wejść w ifa. ## Zadanie 8 :::success Autor: Maria Szlasa ::: :::info ![](https://i.imgur.com/lG09beJ.png) ![](https://i.imgur.com/DQL4qlA.png) ::: Zauważmy, że kiedy zostanie 1 wątek to dostanie on wartość STOP. Policzmy, ile maksymalnie wątków będzie w każdym wierzchołku. * W wierzchołku 0 będzie N wątków. - początek algorytmu. * W wierzchołkach skrajnie lewych (2,5,9...) można się znaleźć idąc ciągle w lewo. Z zadania 7, wiemy, że w każdnym wywołaniu algorytmu w lewo może iść max n-1 wątków. Dlatego w wierzchołku 2 będzie ich N-1, w 5 N-2..., * Analogicznie do poprzedniego podpunktu w skrajnie prawych wierzchołkach (1,3,6) ich ilość będzie się zmiejszała o 1. * Do wierzchołka 4, możemy dojść z wierzchołka 1 lub 2. Załóżmy, że w wierzchołku 1 mamy k1 wątków i w dół poszło k1-1, a w wierzchołku 2 było ich k2 i poszły one w prawo k2-1, więc na 4 mamy max(k1-1,0) + max(k2-1,0) wątków. Ponieważ k1+k2<=N, w 4 mamy N-2 wątki. Możemy zauważyć, że w każdej przekątnej maksymalna ilość wątków będzie o 1 mniejsza od ich ilości na poprzedniej przekątnej. Możemy zauważyć, że w każdej przekątnej maksymalna ilość wątków będzie o 1 mniejsza od ich ilości na poprzedniej przekątnej. Można to udowodnić przeprowadzając analogiczne rozwiązanie co w przypadku wierzchołka nr 4. *** Ponieważ w każdej przekątnej zmniejsza się ich ilość o 1, to dojdziemy do momentu, aż na przekątnej będzie ich 0, zatem każdy wątek otrzyma numer (wynik STOP). Stąd można też wywnioskować, że kształt będzie wyglądał tak jak na obrazku, a liczbę wierzchołków możemy ograniczyć przez ilość przekątnych $1 + 2 + 3 + ... + N = \frac{(N+1)\cdot N}{2}$ ![](https://i.imgur.com/8195alU.jpg) ![](https://i.imgur.com/vqKwoj6.jpg)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully