LINUX.ORG.RU

for ArrayList и thread safety в Java

 


1

1

Скажем есть такой класс

class Test {
	private ArrayList<String> mList;
	
	Test() {
		mList = new ArrayList<String>();
		mList.add("Foo");
		mList.add("Bar");
		mList.add("Baz");
	}
	
	public ArrayList<String> search(String what) {
		ArrayList<String> res = new ArrayList<String>();
		
		for (String str : mList) {
			if (str.indexOf(what) != -1) {
				res.add(str);
			}
		}
		
		return res;
	}
}

Является ли метод search() потокобезопасным? А именно беспокоит одновременное итерирование по mList из разных потоков. Является ли эта операция безовасной при учёте того, что модификации mList не производится во время итерирования?

★★★

Последнее исправление: Olegymous (всего исправлений: 1)

Если два потока будут одновременно добавлять одно и тоже значение, то можно в итоге получить mList с двумя подряд идущими одинаковыми значениями. А если идёт только чтение без изменений списка, то безопасна.

ma1uta ★★★
()

чтение является безопасным в этом случае, при условии что список после заполнения был опубликован потокобезопасным способом.

maxcom ★★★★★
()

Является ли метод search() потокобезопасным?

Да.

«список после заполнения был опубликован потокобезопасным способом»

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

str.indexOf(what) != -1

в java 1.5 есть contains

vtVitus ★★★★★
()
Ответ на: комментарий от Olegymous

А что значит «список после заполнения был опубликован потокобезопасным способом»?

Это значит что твои треды перед использованием List'а должны взять указатель на него в synchronized блоке или из volatile переменной, или из final поля в которое была произведена запись после заполнения списка.

Например:

        private final ArrayList<String> mList;
	
	Test() {
		ArrayList<String> builder = new ArrayList<>();
		builder.add("Foo");
		builder.add("Bar");
		builder.add("Baz");
                mList = builder;
	}

почитай, например, http://stackoverflow.com/questions/801993/java-multi-threading-safe-publication

maxcom ★★★★★
()
Ответ на: комментарий от vtVitus

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

Это не так, так как сам контейнер - изменяемый тип. После его инициализации другие треды могут некоторое время видеть недоконструированный объект если не принять специальных мер чтобы этого небыло

maxcom ★★★★★
()
Ответ на: комментарий от vtVitus

Можно так же попробовать использовать clone при создании результата поиска.

Clone не имеет какой-то мультитредовой семантики и не отменяет необходимость синхронизации

maxcom ★★★★★
()

Если сможешь гарантировать, что завершение конструктора happens before вызовов search, то безопасно (например достаточно mList сделать final, тогда поле будет безопасно опубликовано). А что касается нескольких чтений, то они потокобезопасны. Условием возникновения гонки является несколько доступов, где хотя бы одним является запись, а тут только чтения.

dizza ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.