This document discusses various techniques for process synchronization and concurrency control in distributed systems. It begins by introducing classical problems like the bounded buffer problem and solutions like semaphores. It then covers monitors and condition variables as higher-level synchronization constructs. Various examples of synchronization in real systems like Solaris, Linux, and Windows are provided. The document concludes with a discussion of techniques to ensure atomic transactions in the presence of failures, including log-based recovery, checkpoints, and concurrency control protocols like two-phase locking and timestamp ordering.