Можно ли использовать данный класс в многопоточной среде безопасно?

Как создать в безопасном многопоточном окружении класс для вывода информации о работе программы в консоль и в файл? Какие методы можно использовать для обеспечения безопасности работы класса в многопоточной среде? Желаемо сохранить цельные сообщения при выводе информации.
  • 28 июня 2024 г. 6:32
Ответы на вопрос 2
Этот класс может быть использован в многопоточной среде безопасно, если обеспечить синхронизацию доступа к его методам. 

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

Вот пример простого класса, который выполняет такую задачу:
```java
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Logger {
    private PrintWriter consoleWriter;
    private PrintWriter fileWriter;
    private Lock lock = new ReentrantLock();

    public Logger(String filename) {
        try {
            consoleWriter = new PrintWriter(System.out, true);
            fileWriter = new PrintWriter(new FileWriter(filename), true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void log(String message) {
        lock.lock();
        try {
            consoleWriter.println(message);
            fileWriter.println(message);
        } finally {
            lock.unlock();
        }
    }

    public void close() {
        consoleWriter.close();
        fileWriter.close();
    }
}
```

В данном примере используется мьютекс `ReentrantLock`, чтобы обеспечить синхронизированный доступ к методу `log()`, который выводит информацию как в консоль, так и в файл. Мьютекс блокирует доступ к методу другим потокам, пока один поток не завершит свою операцию.

Таким образом, использование блокировок или мьютексов позволяет обеспечить безопасность работы класса в многопоточной среде и сохранить цельные сообщения при выводе информации.
Не безопасен. <br/> Вы защитили мьютексом только запись в очередь (push), но не чтение из нее (pop). Так что очередь сломается рано или поздно. <br/> Вообще тут лучше бы подошла какая-то специализированная структура со встроенной поддержкой многопоточности, а не стандартные контейнеры. <br/> Можно использовать кольцевой буфер или очередь майкла-скотта. В booste, на сколько помню, есть и то и другое. <br/> Но для начала сгодится и такой вариант. <br/> <br/> Кроме того для вывода на экран в Линукс можно учитывать тот факт, что ОС обеспечивает атомарную запись в консоль для буфера менее PIPE_BUF байт. <a href="https://linux.die.net/man/7/pipe" rel="nofollow">https://linux.die.net/man/7/pipe</a> <br/> Думаю в винде то же есть похожая гарантия, но это не точно. <br/> <br/> Кроме того, операция <code class="cpp">&lt;&lt;</code> для логгирования не очень подходит, т.к. вынуждает использовать конструкции типа: <pre><code class="cpp">oss &lt;&lt; "Error: " &lt;&lt; strerror(err) &lt;&lt; "(" &lt;&lt; err &lt;&lt; ")";</code></pre> <br/> для вывода 1 строки. А это уже не одна запись в очередь, а несколько. Так что защита мьютексом тут не будет гарантией вывода целостной строки. <br/> Для логгера больше подойдет вариант типа std::printf, когда в один вызов передается вся информация для генерации целой строки.
Похожие вопросы