Степан Кольцов, Яндекс.
Самые распространённые примитивы многопоточной синхронизации — это mutex и condvar. Эти примитивы плохо работают в случае contention (т. е. когда несколько потоков заходят в одну критическую область) — операции захвата и отпускания лока начинают работать на порядки медленнее и заметно нагружать CPU, при этом непредсказуемо деградирует производительность системы и появляются другие проблемы. Альтернативный подход к многопоточному программированию — это передача сообщений, или message passing. Степан расскажет о том, как устроены мьютексы, почему возникают такие проблемы и как эффективно реализовать подход message passing.
6. Mutexes are expensive
• mutex lock/unlock takes about 1us under
contention
• under high load it is almost always a
contention
• spinlocks are not worse
23. abstract class Actor {
Actor(Executor executor);
!
// is not called in parallel
protected abstract void act();
!
// execute act()
// at least once
void schedule() { … }
}
Actor
24. class MyReqProcessor: Actor {
MyReqProcessor(Executor exec) { super(exec); }
!
NonBlockingQueue<Request> queue;
!
override void act() {
// is not called in parallel
Vector<Request> reqs = queue.dequeueAll();
// process reqs
}
!
// may be called from different threads
void addWork(Request request) {
queue.enqueue(request);
schedule();
}
}
MyReqProcessor