Zadanie z synchronizacji wielu wątków

Zadanie z synchronizacji wielu wątków
S7
  • Rejestracja:prawie 5 lat
  • Ostatnio:13 dni
  • Postów:354
0

Mam takie zadanie:

Jest most o długości d i nośności w. Na niego będą wjeżdżać auta, a każde z nich ma być reprezentowane przez osobny wątek, auta mają swoją wagę i długość. Pojazdy przed wjazdem mają się kolejkować (wszystkich nie może być więcej niż 25), przy odpowiednich warunkach wjeżdżać na most (musi być wolne miejsce i nie można przekroczyć nośności), poruszać się po nim (nie można wyprzedzać, auta jada tylko w jedna stronę oraz z tego mostu zjeżdżać i kończyć swój żywot. Mogą być to metody enter(), move() i exit() klasy Samochod.

Proszę o pomoc, bo nawet nie jestem w stanie stworzyć konceptu, na razie pomysł miałem taki.
Klasa Bridge (przechowuje wszystkie zmienne związane z mostem, wie ile jest aktualnie pojazdów sume ich mas itd)
Klasa Car dziedziczącą po Thread (osobne watki reprezentujace auta, kazdy z nich ma dostep do Bridge ktory jest jeden i probuje z nim się komunikować)
Klasa BridgeSimulation która jest nadrzędna, generuje watki i dodaje je do kolejek.

no i tak, generujemy wątki i dajemy je do BlockedQueue z ograniczonym rozmiarem do 25
Gdy wątek jest pierwszyw kolejce odpalamy go poprzez .start()
Próbuje wjechać na most, gdy jest to możliwe to na niego wjeżdza //enter()
Przemieszcza sie po nim nie wjezdzajac w inne auta //move()
gdy dojedzie do konca to umiera //exit()

Gdy próbowałem robic ten kod, uzywać synchornized to kończyło się tak, że albo nic nie wjeżdzało na most, albo przesuwało się jedno auto a dopiero potem kolejne, nie mam też pojecia jak zrobić tak, żeby kilka auto przejeżdżało po moscie, patrzac na siebie czy ze soba nie koliduja. (można np. zrobic tablice i sprawdzac pozycje, ale nie wiem jak synchornizować te wątki)


Competitive Google searcher
edytowany 3x, ostatnio: Riddle
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 4 godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10056
1

Współbieżność to jedna z najtrudniejszych rzeczy do ogarnięcia jaką znam w programowaniu. Nie wiem czy jest sens to robić na wątkach.

S7
  • Rejestracja:prawie 5 lat
  • Ostatnio:13 dni
  • Postów:354
0

Też nie widzę sensu tego robić na wątkach, niestety to zadanie na studia :(


Competitive Google searcher
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 4 godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10056
1

No to jeśli dobrze rozumiem to zadanie, to ten "most" ma symbolizować kolejkę thread-safe, do której "wjazd" ma tylko określona liczba wątków (określona na podstawie tych dwóch liczb, czyli długość i waga).

Spodziewam się że jeśli samochody to mają być wątki, to widzę to tak:

  • Albo wszystkie wątki startują od razu (np 1000 wątków się odpala od razu), wszystkie próbują coś wsadzić do kolejki, ale tylko 25 pierwszych z nich da radę pozostałe będą blocked dopóki miejsce w kolejce się nie zwolni
  • Albo tak jak mówisz, że wątki domyślnie nie są odpalone, i dopiero jak jest miejsce w nich to odpalasz .start().

W ogóle to zadanie jest jakoś dziwnie napisane.

Nawet nie do końca jest jasne co ten program ma robić na tak na prawdę- no dobra, ma mieć wątki które wołają jakieś metody enter(), move() ale co te metody niby mają robić? Tylko się wywołać i nic?

edytowany 1x, ostatnio: Riddle
PI
  • Rejestracja:ponad 9 lat
  • Ostatnio:3 miesiące
  • Postów:2787
0

Brzmi ciężko.

Pytanie - skąd wiadomo w którą stronę samochód jedzie? W sensie zakładając układ współrzędnych, i że samochód jest obecnie na polu (x,y) = (2,3), to na jakie pola może się poruszyć?

Myślę, że pierwsze co bym zrobił to mając dane o obecnych współrzędnych samochodu (2,3), oznaczył każde potencjalne pole, na które ten samochód może się poruszyć (czyli np (3,3), (1,3), (2,4), (2,2)) jako "ostrzeżone" dla reszty, albo przynajmniej już na takie, które miałoby w sobie locka (owy "synchronized" - obejmujący jedynie takie "pole z ostrzeżeniem").

EDIT:
Dobra, nie doczytałem że to most, czyli poruszamy się tylko w jednym wymiarze. No to lekka modyfikacja tego co napisałem wyżej.

edytowany 1x, ostatnio: Pinek
Riddle
@Pinek: To chyba ma być jednowymiarowe.
S7
  • Rejestracja:prawie 5 lat
  • Ostatnio:13 dni
  • Postów:354
0
Riddle napisał(a):

Nawet nie do końca jest jasne co ten program ma robić na tak na prawdę- no dobra, ma mieć wątki które wołają jakieś metody enter(), move() ale co te metody niby mają robić? Tylko się wywołać i nic?

metoda enter() ma wprowadzać na most, a move() symuloawć przemieszczanie się po nim


Competitive Google searcher
edytowany 1x, ostatnio: Riddle
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0

Zadanie prawie spoko, poza jednym zdaniem dla mnie:
Przemieszcza sie po nim nie wjezdzajac w inne auta //move()

Jak można wjechać w inne auto przy tak podanym zadaniu?


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 1x, ostatnio: jarekr000000
S7
  • Rejestracja:prawie 5 lat
  • Ostatnio:13 dni
  • Postów:354
0

To jest moja pafraza zadania, żeby były same konkrety, bo w oryginale jest lanie wody i jeszcze fragmenty o wizualizacji


Competitive Google searcher
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0

Bo widzę dwie możliwości - prosta: auto jest albo przed mostem, albo na moście i za mostem. bardziej skomplikowana: auto znajduje się w jakimś punkcie p długości mostu.


jeden i pół terabajta powinno wystarczyć każdemu
S7
Auto znajduje się na jakieś długości p mostu, ma także swoją długość, ma być to wizualizowane mniej więcej [**aa*bbbb*c**]
SL
  • Rejestracja:około 7 lat
  • Ostatnio:około 5 godzin
  • Postów:876
0
Suchy702 napisał(a):

Gdy próbowałem robic ten kod, uzywać synchornized

synchronized to jest uproszczony lock zero jedynkowy: albo coś ma zasób albo nie. W tym wypadku chcesz użyć https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Semaphore.html . permits to jest maksymalna dopuszczalna masa mostu.

Miang
  • Rejestracja:prawie 7 lat
  • Ostatnio:3 minuty
  • Postów:1661
0
Suchy702 napisał(a):

Próbuje wjechać na most, gdy jest to możliwe to na niego wjeżdza //enter()

Gdy próbowałem robic ten kod, uzywać synchornized to kończyło się tak, że albo nic nie wjeżdzało na most, albo przesuwało się jedno auto a dopiero potem kolejne, nie mam też pojecia jak zrobić tak, żeby kilka auto przejeżdżało po moscie, patrzac na siebie czy ze soba nie koliduja. (można np. zrobic tablice i sprawdzac pozycje, ale nie wiem jak synchornizować te wątki)

a jak sprawdzasz czy jest możliwy ten wjazd na most?


dzisiaj programiści uwielbiają przepisywać kod z jednego języka do drugiego, tylko po to by z projektem nadal stać w miejscu ale na nowej technologii
S7
no jezeli auto wjezdza na most to aktualizuje aktualna wage, gdy zjezdza tez ja zmienia. Ponadto ma swoja aktualną pozycje w tablicy, wiec mozna sprawdzic czy "jest miejsce" na moscie
Miang
ale jak sprawdzasz PRZED wjazdem na most czy może wjechać?
S7
no sprawdzam czy aktualna waga na moscie + waga potencjalnego samochodu nie przekraczaja limutu
Miang
a dlaczego dla drugiego samochodu z kolejki to sprawdzenie daje wynik ze przekracza?
S7
Nie rozumiem, kod ponizszy kod powinien tlumaczyc jak probuje to zrobic
S7
  • Rejestracja:prawie 5 lat
  • Ostatnio:13 dni
  • Postów:354
0

Popełniłem taki kod:

Kopiuj
package MultiThreading;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

class Bridge {
    private int length;
    private int capacity;
    private int currentLoad;
    private char[] bridgeState;

    public Bridge(int length, int capacity) {
        this.length = length;
        this.capacity = capacity;
        this.currentLoad = 0;
        this.bridgeState = new char[length];
        initializeBridgeState();
    }

    private void initializeBridgeState() {
        for (int i = 0; i < length; i++) {
            bridgeState[i] = '*';
        }
    }

    public boolean canGo(Car car){
        return currentLoad + car.getWeight() <= capacity && bridgeState[0] == '*';
    }

    public char getPosStatus(int idx){
        return bridgeState[idx];
    }

    public void changePosStatus(int idx, char ch){
        bridgeState[idx] = ch;
    }

    public boolean passedBridge(int position){
        return position == length-1;
    }

    public void displayBridgeState() {
        System.out.println(bridgeState);
    }
}

class Car extends Thread {
    private Bridge bridge;
    private int weight;
    private char name;
    private int position;

    public Car(Bridge bridge, int weight, char name) {
        this.bridge = bridge;
        this.weight = weight;
        this.name = name;
        this.position = 0;
    }

    public int getWeight() {
        return weight;
    }

    private boolean canMove(){
        return bridge.getPosStatus(position+1) == '*';
    }

    public void move(){
        if (canMove()){
            bridge.changePosStatus(position, '*');
            bridge.changePosStatus(position+1, name);
            bridge.displayBridgeState();
        }
    }

    @Override
    public void run() {
        System.out.println("Wlasnie wjechal pojazd: " + name);
        while (!bridge.passedBridge(position)) {
            move();
        }
    }
}

public class BridgeSimulation {
    public static void main(String[] args) {
        Bridge bridge = new Bridge(10, 200);
        BlockingQueue<Car> queue = new LinkedBlockingQueue<>(25);

        for (int i = 0; i < 5; i++){
            queue.add(new Car(bridge, 1, (char) ('a' + i)));
        }

        while (!queue.isEmpty()){
            if (bridge.canGo(queue.peek())){
                Car actCar = queue.poll();
                assert actCar != null;
                actCar.start();
            }

        }
    }
}

Dostaje takie wyjscie, za kazdym razem kolejnosc jest inna:

Kopiuj
Wlasnie wjechal pojazd: b
Wlasnie wjechal pojazd: e
Wlasnie wjechal pojazd: c
Wlasnie wjechal pojazd: d
Wlasnie wjechal pojazd: a
*b********

Dlaczego watki wygladaja jakby nie uruchamialy sie po kolei? I jak zrobic zeby robily to wlasnie po kolei.
tylko jedno auto sie poruszylo i stoi w miejscu, nie jedzie dalej, dlaczego?

Dla uproszczenia dlugosc kazdego samochodu to 1, waga tak samo wiec nie gra roli


Competitive Google searcher
Miang
gdzie uaktualniasz position dla samochodu?
S7
Rzeczywiście tego nie robie, dziękuje
Miang
  • Rejestracja:prawie 7 lat
  • Ostatnio:3 minuty
  • Postów:1661
2

a dlaczego miałyby działać po kolei skoro to są osobne wątki?


dzisiaj programiści uwielbiają przepisywać kod z jednego języka do drugiego, tylko po to by z projektem nadal stać w miejscu ale na nowej technologii
Riddle
Wiekopomna chwila. Właśnie pierwszy raz dałem plusa osobie @Miang
S7
okej, jak dodam sleep(100) to zaczyna to dzialac mniej wiecej tak jak mysle
S7
  • Rejestracja:prawie 5 lat
  • Ostatnio:13 dni
  • Postów:354
0

Po dodaniu sleep(100) w

Kopiuj
        //glowna petla
        while (!queue.isEmpty()){
            sleep(100);
            if (bridge.canGo(queue.peek())){
                Car actCar = queue.poll();
                assert actCar != null;
                actCar.start();
            }
        }
Kopiuj
    //run w klasie Car
    @Override
    public void run() {
        System.out.println("Wlasnie wjechal pojazd: " + name);
        while (!bridge.passedBridge(position)) {
            move();
            try {
                sleep(100); // Dodatkowe oczekiwanie dla czytelności wyjścia
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

auta zaczynaja uruchamiac sie po kolei, natomiast dalej dochodzi tylko do jednego przesuniecia

Kopiuj
Wlasnie wjechal pojazd: a
*a********
Wlasnie wjechal pojazd: b
Wlasnie wjechal pojazd: c
Wlasnie wjechal pojazd: d
Wlasnie wjechal pojazd: e

Competitive Google searcher
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 4 godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10056
2

@Suchy702: Ale to nie ma sensu, bo to jest normalne w wątkach że one się nie uruchomią po kolei - na tym polega współbieżność. Z resztą, co to miałoby znaczyć "po kolei", przecież kod wątkach działa równocześnie.

edytowany 1x, ostatnio: Riddle
S7
ale uruchomienie nie działa równocześnie, tylko po kolei
Riddle
@Suchy702: Jeśli masz zadanie z wątków, i ich celem jest to, żebyś nauczył się wątków, to oswój się z myślą że w wątkach nie ma czegoś takiego jak "kolejność". One działają równocześnie.
FD
  • Rejestracja:ponad rok
  • Ostatnio:ponad rok
  • Postów:39
0

Wątki nie są trzymane w queue, która kolejka może być czytana od tyłu lub od przodu jako lifo i fifo, wtedy by się uruchamiały jeden po drugim.

Ale w systemie operacyjnym są przetrzymywane w red black tree, więc jak dajesz syscall utworzenia thread, czyli clone, to wtedy dodajesz do samo balansującego drzewa, jak jakaś inna aplikacja zrobi wątek czy uruchomi proces to znowu przebiega balans drzewa na podstawie wag.
To jest też nazywane na linuxie completly fair scheduling.

Różnie może się te drzewo zbalansować i potem jest dequeue z tego drzewa, balansowane jest na podstawie wag, kernelowe thready są wyżej w rankingu i nie ma rozróżnienia między procesami i wątkami.

Żeby jako tako synchronizację zrobić, wykorzystałeś sleep, który działa w miarę bo poczekałeś aż wystartuje wątek pierwszy i dopiero następny utworzyłeś itp.

Można też jakieś tricki ze state machine zrobić i mutexami, gdzie wątek robi mutexa, ale jak nie jest maszyna stanów na jego wątku to odblokowuje i idzie czekać, a jak jest to blokuje, wykonuje swoje modyfikując uwspólnione struktury danych, inkrementuje maszynę stanów do następnego pojazdu i wychodzi.
Ale to też problemów dużo rodzi, bo nawet dokładnej treści zadania nie wiadomo, aczkolwiek możesz też to jakoś wykorzystać.

Będziesz musiał na pewno trochę pokombinować, używaj to co masz od semafor, mutexów, atomic operations, czy samych struktur thread safe, coś wymyślisz.

Miang
to jak są trzymane to chyba nieudokumentowana właściwość która inaczej zadziała na innym systemie. A w zadaniu chyba chodzi o to żeby zgodnie z regułami sztuki je wykonać, Przypuszczam ze było powiedziane na zajęciach co należy użyć ;) Nie wiem czy w javowych wątkach jest jakiś odpowiednik sygnałów ?
FD
@Miang: no tak jest, w sumie nawet od 6.0 wersji dali ulepszoną wersję schedulera, która dość dużo z 20% dawała performancu, można też ręcznie sobie zmienić, na windowsie gorzej bo tam trudniej coś zmodyfikować. A java też jakoś tam po swojemu syscalle systemowe wywołuje, sygnały potrafią budzić wątki to można nawet uśpić wszystkie i budzić tylko wybrane do pracy, ale sygnały są na linuxie, na windowsie nie ma, jako że nie znam aż tak javy, a java jest przenośna to jak nie ma odpowiednika czegoś na innych systemach, to powinno nie być, ale kto wie czy nie wymyślili czegoś:>
SZ
  • Rejestracja:prawie 2 lata
  • Ostatnio:3 miesiące
  • Postów:52
1

Spróbuj private volatile char[] bridgestate. Prawdopodobnie dochodzi do hoisting na głównej petli. Ale jak usuniesz sleep to i tak pojawią się znowu problemy. Może semafor z 25 uprawnieniami i atomic reference do stanu mostu jako record(zapis i odczyt).

edytowany 1x, ostatnio: Riddle
c3r
  • Rejestracja:ponad 7 lat
  • Ostatnio:około rok
  • Lokalizacja:Kraków
  • Postów:18
1

Szczerze mówiąc, to zadanie brzmi jak typowy problem semaforowy, gdzie procesy (auta) walczą o dostęp do zasobów (waga i miejsce na moście). Ja bym podszedł do tego w sten sposób żeby rozszerzyć (skomponować) klasę z java.util.concurrent.Semaphore i przeciążyć metody acquire() i release().

Zobacz pozostałe 7 komentarzy
Miang
widziałeś kiedyś wjazd na most w rzeczywistości?
Riddle
@Miang: za bardzo się skupiasz na analogii. Może jeszcze powiesz że do klasy Car musimy dodać pola koła, podwozie, skrzynia biegów, przednia szyba, a do mostu to wiadomo, podpory i zróbmy też klasę rzeka, bo mosty są nad rzeką.
Riddle
W nawiasie jest wyjaśnione co to znaczy kolejkować - wszystkich nie może być więcej niż 25. Odnośnie kolejności nie ma specyfikacji. Dodawanie na siłę kolejnosci bo ktoś użył słowa "most" to moim zdaniem już niepotrzebna komplikacja. Rozwiązanie od @c3r jest w porządku.
Miang
prowadzący jakieś zajęcia: podam problem ze świata rzeczywistego nie będę musiał opisywać tak dokładnie, @Riddle : potrzymaj mi komentarz
Riddle
@Miang: Jeśli prawdą by było, że pojazdy mają wjeżdżać na most po kolei (tak jak na most), i mają jechać mostem po kolei bez wyprzedzania tak jak na moście, i mają się zjechać z mostu po kolei tak jak na moście - to zastanów się: Po kiego kija miałyby być tutaj wątki? ;| Przecież jeśli one wszystkie miałyby wjechać, jechać i wyjechać po kolei, to załatwiłby to zwykły while bez żadnego wątku. W ogóle współbieżność by tu nie była użyta. W takim rozwiązaniu w każdym momencie maksymalnie jeden wątek by działał.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)