2009-11-09 4 views
6

Из-за примеров наводнения при использовании регистратора с использованием шаблона Singleton я только что написал простой регистратор C++ в том же подходе для моей программы. Тем не менее, поскольку известный метод блокировки с двойной проверкой, как известно, не более потокобезопасен, мне интересно:Простой регистратор C++ с использованием шаблона singleton

1) Забудьте об использовании шаблона Singleton в этом случае?

2) Продолжайте использовать блокировку с двойной проверкой, даже если она небезопасна?

3) Использовать дорогостоящий метод блокировки чистой синхронизации для каждого доступа к его общедоступным интерфейсам?

Любые предложения?

+1

Вау, я не ожидал, что ответы придут так быстро. Я просто понимаю, что совершил тупую ошибку. В моем случае в основном есть две группы интерфейсов, которые требуют защиты: getInstance(), а остальные - для клиента регистратора для инициализации различных параметров журнала. Моя ошибка заключалась в том, что я потратил много времени, чтобы найти подход, который будет защищать оба типа интерфейсов, надеюсь, с сбалансированной эффективностью. Почему я должен использовать один и ТОЛЬКО один подход? Я могу использовать либо предложение от Arkaitz, либо stefaanv для getInstance(); затем используйте базовую синхронизацию для инициализации настроек. – shiouming

ответ

16

Использование Meyers Singleton. Если вы используете gcc, то хотя бы инициализация является потокобезопасной. строительство

class Singleton{ 
    Singleton(){ 
    //This is threadsafe in gcc, no mutex required 
    } 
    static Singleton * instance(){ 
     static Singleton myinstance; 
     return &myinstance; 
    } 
}; 

НКУ охранников статического местных жителей, если не отключить с -fno-THREADSAFE-статикой, я недавно писал о том, что here

+0

Не хотите ли, чтобы instance() был статичным? – Aaron

+0

Аарон, ты прав. –

+0

+1 для этой заметки я как-то потратил достаточно времени на эту проблему с компилятором WindRiver C/C++ (бывший Diab). –

1

В приложениях с нитями, я предпочитаю использовать одиночка с Initialize() функцией и утверждает, что initialize() используется до первого экземпляра(). Вызовите initialize() из основного потока. Я не думаю, что ленивый экземпляр действительно является ключевой особенностью синглтона, особенно для регистратора.

В то время как ответ Arkaitz более изящный, в моих ответах избегаются проблемы с потоками на всех платформах с стоимостью 1 дополнительной функции и некоторыми проблемами, возникающими при запуске для синглонов с зависимостями (чему помогают утверждения и, конечно же, разумно использовать синглтоны).

+0

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

+0

@ Майкл: Когда мы решили для этого подхода, я на самом деле предложил использовать ваш ответ: доступ в основной поток. Но этот подход работает для нас, и он гарантирует, что синглтон всегда инициализируется в основном потоке. Если доступ будет удален из основного потока, мы найдем только первый раз, когда возникнет проблема (в поле?) – stefaanv

+0

Мой существующий код довольно близок к этому подходу. Тем не менее, я также задаюсь вопросом, следует ли мне предположить, что клиентский код регистратора всегда будет правильно использовать/инициализировать регистратор, или я должен выполнить проверку внутри. – shiouming

1

Один из подходов - убедиться, что ваш первый доступ к регистратору приходит до того, как ваше приложение запустит второй поток. Получая доступ к синглтону в то время, когда вы ЗНАЕТЕ, что нет никаких конфликтов, вы убедитесь, что последующие обращения всегда найдут ранее существовавший объект, и вы должны полностью избежать проблемы.

0

Вам не нужна отдельная функция Initialize(), так как это просто загрязнит ваш одноэлементный интерфейс. Просто получите экземпляр singleton

прежде, чем какая-либо другая ветка имеет доступ к нему.

+0

Вам не нужно проверять синглтон для NULL. Он существует или не выходит. Возвращая ссылку на синглтонную gurantess, она существует. –

+0

Спасибо, Марк. Я согласен с тем, что singleton getter должен возвращать ссылку, а не указатель. Моя строка относится к обрезанию о Майерс синглтон выше, что возвращает его по указателю. Хотя кажется, что он не может потерпеть неудачу, вы никогда не знаете, кто будет изменять ваш код в будущем. Таким образом, VERIFY - это всего лишь капсула времени для будущего программиста. – BostonLogan

Смежные вопросы