Кольцов Степан рассказывает о многопоточной синхронизации — mutex и condvar. Объясняет, почему они плохо работают в случае contention. Говорит об альтернативном подходе к многопоточному программированию — передаче сообщений, или message passing. Рассказывает, как устроены мьютексы, почему возникают проблемы и как эффективно реализовать подход message passing.
- What’s wrong with mutex?
- Hard to write safe code
- void first
- void foo
- Mutexes are expensive
- struct spinlock lock = SPINLOCK_INIT
- struct spinlock { int locked; }
- Code examples github.com/stepancheg/no-mutex-c github.com/stepancheg/no-mutex
- struct mutex lock = MUTEX_INIT
- struct mutex { int locked; // 1 if locked int count; // number of threads requesting a lock }
- Numbers lock cmpxchg 8ns uncont. mutex lock/unlock 11ns futex_wake 400ns cont. mutex lock ~500ns
- Hard to parallelize
- There’s a solution!
- Message passing/ Actor model
- class BlockingQueue
- Simple message passing with dedicated thread
- // non-blocking queue // mutex+condvar BlockingQueue<Request> queue
- Actors
- interface Runnable { void run(); } ! interface ThreadPoolExecutor { void submit(Runnable); } Executor
- abstract class Actor { Actor(Executor executor)
- class MyReqProcessor: Actor { MyReqProcessor(Executor exec) { super(exec); }
- enum ETaskState { WAITING, RUNNING, RUNNING_GOT_TASKS, }