Действительно ли эта свободная от блокировок очередь.NET ориентирована на многопотоковое исполнение?

Доступ MS не исправляет пространство для записей, пока Вы не уплотнили базу данных.

Это - что-то, что необходимо регулярно делать к базе данных доступа как часть Вашего обслуживание иначе, Вы закончите с некоторыми довольно болезненными проблемами.

можно уплотнить базу данных любой через Доступ MS, UI (Инструменты-> Утилиты Базы данных->
Компактный и База данных Восстановления) Вас может использовать использование командной строки:

msaccess.exe "target database.accdb" /compact 

N.B. Компактный переключатель / должен быть после целевой базы данных

6
задан Community 23 May 2017 в 12:25
поделиться

6 ответов

Microsoft Research CHESS should prove to be a good tool for testing your implementation.

7
ответ дан 8 December 2019 в 13:00
поделиться

Учитывая, что я не могу найти никаких ссылок на то, что Interlocked.Exchange выполняет блоки чтения или записи, я бы сказал, что нет. Я также хотел бы спросить, почему вы хотите отказаться от блокировки, поскольку редко дает достаточно преимуществ, чтобы противостоять его сложности.

Microsoft представила отличную презентацию на GDC в 2009 году, и вы можете получить слайды здесь .

3
ответ дан 8 December 2019 в 13:00
поделиться

Я подозреваю, что это небезопасно для потоков - представьте себе следующий сценарий:

два потока входят в курсор. Запишите . Первый доходит до строки node = new Node (x, node); в истинной половине оператора if (current == BUFFER_SIZE) (но давайте также предположим, что current == BUFFER_SIZE ), поэтому, когда 1 добавляется к current , тогда другой входящий поток будет следовать по другому пути через оператор if. Теперь представьте, что поток 1 теряет свой временной интервал, а поток 2 получает его и переходит к вводу оператора if, ошибочно полагая, что условие все еще выполняется. Он должен был ввести другой путь.

Я тоже не запускал этот код, поэтому я не уверен, возможны ли мои предположения в этом коде, но есть ли они (т.е. ввод курсора.

1
ответ дан 8 December 2019 в 13:00
поделиться

First, I wonder about the assumption in these two lines of sequential code:

                node.data[current++] = x;

                // We have to use interlocked, to assure that we incremeent the count 
                // atomicalluy, because the reader could be reading it.
                Interlocked.Increment(ref node.count);

What is to say that the new value of node.data[] has been committed to this memory location? It is not stored in a volatile memory address and therefore can be cached if I understand it correctly? Doesn't this potentially lead to a 'dirty' read? There may be other places the same is true, but this one stood out at a glance.

Second, multi-threaded code that contains the following:

Thread.Sleep(int);

... is never a good sign. If it's required then the code is destined to fail, if it isn't required it's a waste. I really wish they would remove this API entirely. Realize that is a request to wait at least that amount of time. With the overhead of context switching your almost certainly going to wait longer, a lot longer.

Third, I completely don't understand the use of the Interlock API here. Maybe I'm tired and just missing the point; but I can't find the potential thread conflict on both threads reading & writing to the same variable? It would seem that the only use I could find for interlock exchange would be to modify the contents of node.data[] to fix #1 above.

Lastly it would seem that the implementation is somewhat over-complicated. Am I missing the point of the whole Cursor/Node thing or is it basically doing the same thing as this class? (Note: I haven't tried it and I don't think this is thread safe either, just trying to boil down what I think your doing.)

class ReaderWriterQueue<T>
{
    readonly AutoResetEvent _readComplete;
    readonly T[] _buffer;
    readonly int _maxBuffer;
    int _readerPos, _writerPos;

    public ReaderWriterQueue(int maxBuffer)
    {
        _readComplete = new AutoResetEvent(true);
        _maxBuffer = maxBuffer;
        _buffer = new T[_maxBuffer];
        _readerPos = _writerPos = 0;
    }

    public int Next(int current) { return ++current == _maxBuffer ? 0 : current; }

    public bool Read(ref T item)
    {
        if (_readerPos != _writerPos)
        {
            item = _buffer[_readerPos];
            _readerPos = Next(_readerPos);
            return true;
        }
        else
            return false;
    }

    public void Write(T item)
    {
        int next = Next(_writerPos);

        while (next == _readerPos)
            _readComplete.WaitOne();

        _buffer[next] = item;
        _writerPos = next;
    }
}

So am I totally off-base here and am failing to see the magic in the original class?

I must admit one thing, I despise Threading. I've seen the best developers fail at it. This article gives a great example on how hard it is to get threading right: http://www.yoda.arachsys.com/csharp/singleton.html

1
ответ дан 8 December 2019 в 13:00
поделиться

Наличие Sleep () делает подход без блокировки совершенно бесполезным. Единственная причина столкнуться со сложностями проектирования без блокировок - это потребность в абсолютной скорости и во избежание затрат на семафоры. Использование Sleep (1) полностью противоречит этой цели.

4
ответ дан 8 December 2019 в 13:00
поделиться

Остерегайтесь двойной проверки - шаблон одиночной блокировки (как в приведенной выше ссылке: http://www.yoda.arachsys.com/csharp/singleton.html )

Дословная цитата из «Современного дизайна C ++» Андрея Александреску

    Очень опытные многопоточные программисты знают, что даже шаблон блокировки с двойной проверкой, хотя и верен на бумаге, не всегда верен на практике. В некоторых симметричных многопроцессорных средах (в которых используется так называемая расслабленная модель памяти) записи совершаются в основную память пакетами, а не по очереди. Пакеты происходят в порядке возрастания адресов, а не в хронологическом порядке. Из-за такого переупорядочивания операций записи память, видимая одним процессором за раз, может выглядеть так, как если бы операции не выполнялись в правильном порядке другим процессором. Конкретно, присвоение pInstance_, выполняемое процессором, может произойти до того, как объект Singleton будет полностью инициализирован! Таким образом, к сожалению, известно, что шаблон блокировки с двойной проверкой неисправен для таких систем.
2
ответ дан 8 December 2019 в 13:00
поделиться