← Static tasks

1114. Print in Order

leetcode easy

#array#csharp#easy#leetcode

Task

Предположим, у нас есть класс:

public class Foo {

public void first() { print("first"); }

public void second() { print("second"); }

public void third() { print("third"); }

}

Один и тот же экземпляр Foo будет передан трем разным потокам. Поток A вызовет first(), поток B вызовет second(), и поток C вызовет third(). Спроектируйте механизм и модифицируйте программу, чтобы гарантировать, что second() выполняется после first(), а third() выполняется после second().

Примечание:

Мы не знаем, как потоки будут планироваться в операционной системе, даже если числа в вводе подразумевают порядок выполнения. Формат ввода, который вы видите, в основном предназначен для обеспечения полноты наших тестов.

Пример:

Input: nums = [1,2,3]

Output: "firstsecondthird"

Explanation: There are three threads being fired asynchronously. The input [1,2,3] means thread A calls first(), thread B calls second(), and thread C calls third(). "firstsecondthird" is the correct output.

C# solution

matched/original
using System;
using System.Threading;
public class Foo {
    private SemaphoreSlim firstJobDone = new SemaphoreSlim(0, 1);
    private SemaphoreSlim secondJobDone = new SemaphoreSlim(0, 1);
    public void First(Action printFirst) {
        printFirst();
        firstJobDone.Release();
    }
    public void Second(Action printSecond) {
        firstJobDone.Wait();
        printSecond();
        secondJobDone.Release();
    }
    public void Third(Action printThird) {
        secondJobDone.Wait();
        printThird();
    }
}

C++ solution

auto-draft, review before submit
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
public class Foo {
    private SemaphoreSlim firstJobDone = new SemaphoreSlim(0, 1);
    private SemaphoreSlim secondJobDone = new SemaphoreSlim(0, 1);
    public void First(Action printFirst) {
        printFirst();
        firstJobDone.Release();
    }
    public void Second(Action printSecond) {
        firstJobDone.Wait();
        printSecond();
        secondJobDone.Release();
    }
    public void Third(Action printThird) {
        secondJobDone.Wait();
        printThird();
    }
}

Java solution

matched/original
class Foo {

  private AtomicInteger firstJobDone = new AtomicInteger(0);
  private AtomicInteger secondJobDone = new AtomicInteger(0);

  public Foo() {}

  public void first(Runnable printFirst) throws InterruptedException {
    printFirst.run();
    firstJobDone.incrementAndGet();
  }

  public void second(Runnable printSecond) throws InterruptedException {
    while (firstJobDone.get() != 1) {
    }
    printSecond.run();
    secondJobDone.incrementAndGet();
  }

  public void third(Runnable printThird) throws InterruptedException {
    while (secondJobDone.get() != 1) {
    }
    printThird.run();
  }
}

Python solution

matched/original
from threading import Semaphore

class Foo:
    def __init__(self):
        self.firstJobDone = Semaphore(0)
        self.secondJobDone = Semaphore(0)

    def first(self, printFirst):
        printFirst()
        self.firstJobDone.release()

    def second(self, printSecond):
        self.firstJobDone.acquire()
        printSecond()
        self.secondJobDone.release()

    def third(self, printThird):
        self.secondJobDone.acquire()
        printThird()

Go solution

matched/original
package main

import (
    "sync"
)

type Foo struct {
    firstJobDone  sync.Mutex
    secondJobDone sync.Mutex
}

func NewFoo() *Foo {
    f := &Foo{}
    f.firstJobDone.Lock()
    f.secondJobDone.Lock()
    return f
}

func (f *Foo) First(printFirst func()) {
    printFirst()
    f.firstJobDone.Unlock()
}

func (f *Foo) Second(printSecond func()) {
    f.firstJobDone.Lock()
    printSecond()
    f.firstJobDone.Unlock()
    f.secondJobDone.Unlock()
}

func (f *Foo) Third(printThird func()) {
    f.secondJobDone.Lock()
    printThird()
    f.secondJobDone.Unlock()
}

Explanation

Algorithm

1⃣Инициализация переменных:

Инициализируйте координационные переменные firstJobDone и secondJobDone, чтобы указать, что задания еще не выполнены.

2⃣Функция first():

В этой функции нет зависимости, поэтому можно сразу приступить к выполнению задания. В конце функции обновите переменную firstJobDone, чтобы указать, что первое задание выполнено.

3⃣Функции second() и third():

В функции second() проверьте статус firstJobDone. Если она не обновлена, подождите, иначе переходите к выполнению второго задания. В конце функции обновите переменную secondJobDone, чтобы отметить завершение второго задания.

В функции third() проверьте статус secondJobDone. Аналогично функции second(), подождите сигнала secondJobDone перед тем, как приступить к выполнению третьего задания.

😎