На жаль, простота створення потоків часом "компенсується" складністю їх застосування. Дві типові проблеми, з якими програміст може зіткнутися при роботі з потоками, - це тупики (deadlocks) і гонки (race conditions). Тупік. Тупики мають місце, коли потік чекає ресурс, який в даний момент належить іншому потоку. Розглянемо приклад. Потік 1 захоплює ресурс А, і для того щоб продовжувати роботу, чекає можливості захопити ресурс Б. У той же час Потік 2 захоплює ресурс Б і чекає можливості захопити ресурс А. Розвиток цього сценарію заблокує обоє потоку; жоден з них не виконуватиметься. Ресурсами можуть виступати будь-які спільно використовуються об'єкти системи - файли, масиви в пам'яті, пристрої введення / виводу і т. п. Гонки Ситуація гонок виникає, коли два або більше потоку намагаються отримати доступ до загального ресурсу і змінити його стан. Розглянемо наступний приклад. Нехай Потік 1 отримав доступ до ресурсу і змінив його в своїх інтересах; потім активізувався Потік 2 і модифікував цей же ресурс до завершення Потоку 1. Потік 1 вважає, що ресурс залишився у тому ж стані, в якому був до перемикання. Залежно від того, коли саме був змінений ресурс, результати можуть змінюватись - іноді код буде виконуватися нормально, іноді ні Inc (i); if i = iSomething then DoSomething; Тут i - глобальна змінна, доступна з обох потоків. Нехай два або більше потоків виконують цей код одночасно. Потік 1 інкрементував значення змінної i і хоче перевірити її значення для виконання тих чи інших умов. Але тут активізується інший потік, який ще збільшує значення i. У результаті перший потік "проскакує" повз умови, яка, здавалося б, мало бути виконано.