powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / codereview самописный потокобезопасный stack
20 сообщений из 120, страница 5 из 5
codereview самописный потокобезопасный stack
    #39401192
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей Арсеньев Поэтому либо полная остановка изменяющих нитей, либо не актуальность.

Ну в теории ведь есть multi CAS, допустим хранить счетчик размера стэка в отдельном поле и CASиться по нему и верху стэка. Не практично само собой, так, чтоб дискуссию поддержать:)
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401201
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей АрсеньевНо тогда можно пользоваться только синхро коллекцией. А в чем смысл?Смысл в актуальности (:
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401204
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
забыл никСергей Арсеньев Поэтому либо полная остановка изменяющих нитей, либо не актуальность.

Ну в теории ведь есть multi CAS, допустим хранить счетчик размера стэка в отдельном поле и CASиться по нему и верху стэка. Не практично само собой, так, чтоб дискуссию поддержать:)

а как это сделать?

одновременно CASиться по размеру и по неизменной голове стека?

код, плиз
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401215
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
/**
 * Returns the number of elements in this queue.  If this queue
 * contains more than {@code Integer.MAX_VALUE} elements, returns
 * {@code Integer.MAX_VALUE}.
 *
 * <p>Beware that, unlike in most collections, this method is
 * <em>NOT</em> a constant-time operation. Because of the
 * asynchronous nature of these queues, determining the current
 * number of elements requires an O(n) traversal.
 * Additionally, if elements are added or removed during execution
 * of this method, the returned result may be inaccurate.  Thus,
 * this method is typically not very useful in concurrent
 * applications.
 *
 * @return the number of elements in this queue
 */
public int size() {
    int count = 0;
    for (Node<E> p = first(); p != null; p = succ(p))
        if (p.item != null)
            // Collection.size() spec says to max out
            if (++count == Integer.MAX_VALUE)
                break;
    return count;
}

тынц
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401216
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Usman,

а это на что ответ?
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401217
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

По поводу реализации метода size()
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401246
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут на самом деле 3 варианта (по степени возростания консистентности (отражения реального положения дел в стеке)):
1. Тупо получить ссылку на топ и пройтись до null, просуммировав количество элементов
Это O(n)
2. Добавить AtomicLong и перед put/pop инкрементить/декрементить
Это O(1)
3. Добавить поле long index в Entry, и присваивать его в момент создания Entry, тогда получить размер будет - topPointer.get().index;
Это тоже O(1). Здесь тоже возможна ситуация когда между topPointer.get() и получением поля index будет вставлен(ы) элемент(ы), но операций требуется значительно меньше, чем с AtomicLong. Мое имхо, мне больше нравится этот способ : ).

В ConcurrentLinkedList по O(1) размер уже не вернешь видимо...
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401251
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
no568923. Добавить поле long index в Entry, и присваивать его в момент создания Entry, тогда получить размер будет - topPointer.get().index;
Это тоже O(1). Здесь тоже возможна ситуация когда между topPointer.get() и получением поля index будет вставлен(ы) элемент(ы), но операций требуется значительно меньше, чем с AtomicLong. Мое имхо, мне больше нравится этот способ : ).

В ConcurrentLinkedList по O(1) размер уже не вернешь видимо...

Ну взяли вы индекс - например 9, начали создавать Entry, заснули, пришло еще 3 потока, индекс уже 12, это не вариант
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401252
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл никno568923. Добавить поле long index в Entry, и присваивать его в момент создания Entry, тогда получить размер будет - topPointer.get().index;
Это тоже O(1). Здесь тоже возможна ситуация когда между topPointer.get() и получением поля index будет вставлен(ы) элемент(ы), но операций требуется значительно меньше, чем с AtomicLong. Мое имхо, мне больше нравится этот способ : ).

В ConcurrentLinkedList по O(1) размер уже не вернешь видимо...

Ну взяли вы индекс - например 9, начали создавать Entry, заснули, пришло еще 3 потока, индекс уже 12, это не вариант
Индекс присваивается до CAS, если пришло еще 3 потока, то когда проснемся CAS не пройдет, цикл повторится и уже будем новый индекс вставлять...
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401255
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerзабыл никпропущено...


Ну в теории ведь есть multi CAS, допустим хранить счетчик размера стэка в отдельном поле и CASиться по нему и верху стэка. Не практично само собой, так, чтоб дискуссию поддержать:)

а как это сделать?

одновременно CASиться по размеру и по неизменной голове стека?

код, плиз

Ага, может еще и ключи от квартиры? Я же говорю, что в ТЕОРИИ.
Просто лень напрягать мозги в выдуманной ситуации, то что метод size() в конкурентной коллекции может выдавать не всегда конкретные ответы, это разумный компромисс.
Но, если бы вдруг мне понадобилось что-нибудь этакое, на multi-CAS, я бы начал смотреть вот отсюда - AtomicMarkableReference
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401256
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
no56892Индекс присваивается до CAS, если пришло еще 3 потока, то когда проснемся CAS не пройдет, цикл повторится и уже будем новый индекс вставлять...

Я немного запутался о какой версии кода вы уже тут говорите:) Как у вас CAS от индекса зависит? Я к тому что compareAndSwapить будете?
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401262
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл ник,

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
class ConcurrentStack<E> {
	
	private final AtomicReference<Entry<E>> pointer = new AtomicReference<>();
	
	public void push(E element) {
		boolean finish = false;
		final Entry<E> newTop = new Entry<>(element);
		do {
			Entry<E> currentTop = pointer.get();
			newTop.setPrev(currentTop);
			finish = pointer.compareAndSet(currentTop, newTop);
		} while(!finish);
	}
	
	public E pop() {
		E ret = null;
		boolean finish = false;
		do {
			Entry<E> currentTop = pointer.get();
			Entry<E> newTop = null;
			if(currentTop != null) {
				ret = currentTop.element;	
				newTop = currentTop.prev;
			} else {
				return null;
			}
			finish = pointer.compareAndSet(currentTop, newTop);
		} while(!finish);
		return ret;
	}
	
	public long size() {
		Entry<E> current = pointer.get();
		return current != null?current.index:0;
	}
	
	private static class Entry<E> {
		private E element; 
		private Entry<E> prev; 
		private long index = 1;

		Entry(E element) {
			this.element = element;
		}
		
		void setPrev(Entry<E> prev) {
			this.prev = prev;
			if(prev != null) {
				index = prev.index + 1;
			}
		}
	}
}
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401266
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
UsmanСергей АрсеньевНо тогда можно пользоваться только синхро коллекцией. А в чем смысл?Смысл в актуальности (:
А как синхроколлекция даст актуальность?
Ведь в момент return число может стать уже не соответствующим действительности.
В силу этого ни о какой актуальности речи не будет.
Блокировка должна быть до конца применения значения size(), типа:
Код: java
1.
if(stack.size()>0) stack.pull().toString();

может вызвать NPE.
Посему какая разница неправильный размер он был получен внутри или снаружи.
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401267
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл никЯ немного запутался о какой версии кода вы уже тут говорите:) Как у вас CAS от индекса зависит? Я к тому что compareAndSwapить будете?
Он имеет ввиду, что присвоение одному AtomicReference (ссылки на голову) и увеличение другого AtomicInteger (счетчика) одновременно не сделаешь. А значит size на основе счетчика может вернуть не правду. Правда оно и не важно. :)
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401269
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей Арсеньев,

Конечно если не делать вариант, что Entry сразу хранит счетчик. :)
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401276
no56892
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей Арсеньев Блокировка должна быть до конца применения значения size()
В таком варианте да, а вот например:
Код: java
1.
2.
3.
if(concurrentStack.size() > 100) {
  //increase number of popping threads
}


вполне себе нормально
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401284
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей АрсеньевА как синхроколлекция даст актуальность?на момент возвращения будет актуальное значениеСергей АрсеньевВедь в момент return число может стать уже не соответствующим действительности.в момент выхода из синхро-блока (если потоки все еще "крутятся")
Сергей АрсеньевВ силу этого ни о какой актуальности речи не будет.см. 20194593 :

Код: plaintext
Thus, this method is typically not very useful in concurrent applications.

Сергей АрсеньевБлокировка должна быть до конца применения значения size()А вот тут я соглашусь.
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401328
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
no568922. Добавить AtomicLong и перед put/pop инкрементить/декрементить
Это O(1)


а можно ведь только однажды это сделать перед возвращением значения пользователю
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401393
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл никНу взяли вы индекс - например 9, начали создавать Entry, заснули, пришло еще 3 потока, индекс уже 12, это не вариант
Entry засунется только тогда, когда между ним и головой никто не успел всунуться.
Если успели все одно Entry переделывать перед новой попыткой вставки.
Так что метод относительно действенный. Если только не бесполезный.
...
Рейтинг: 0 / 0
codereview самописный потокобезопасный stack
    #39401396
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerno568922. Добавить AtomicLong и перед put/pop инкрементить/декрементить
Это O(1)

а можно ведь только однажды это сделать перед возвращением значения пользователю
Только вот то, что запрос значения может оказаться раньше инкремента/декремента может привести к тому, что значение будет чуть менее чем полностью отличаться от актуального.
Что правда не важно. :)
...
Рейтинг: 0 / 0
20 сообщений из 120, страница 5 из 5
Форумы / Java [игнор отключен] [закрыт для гостей] / codereview самописный потокобезопасный stack
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]