What are the key differences between optimistic and pessimistic locking, and how do you implement them?